CCSDK DCAE dashboard feature changes 56/111056/5
authorKotagiri, Ramprasad (rp5662) <rp5662@att.com>
Fri, 7 Aug 2020 19:54:10 +0000 (15:54 -0400)
committerKotagiri, Ramprasad (rp5662) <rp5662@att.com>
Wed, 12 Aug 2020 16:38:26 +0000 (12:38 -0400)
Issue-ID: DCAEGEN2-1857
Issue-ID: DCAEGEN2-2074
Issue-ID: DCAEGEN2-2364

Change-Id: I97f5ec4599512ed848136971b11d4c2a137a4999
Signed-off-by: Kotagiri, Ramprasad (rp5662) <rp5662@att.com>
182 files changed:
ccsdk-app-common/pom.xml
ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/ApiBaseController.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/NbApiController.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PaginatedResultsRetrievedEvent.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PagingEventListener.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CloudifyController.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CommonApiController.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ConsulController.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardHomeController.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DashboardRestrictedBaseController.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/DeploymentHandlerController.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/ECDSingleSignOnController.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/HealthCheckController.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/InventoryController.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/ControllerEndpoint.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/EcdComponent.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployment.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentRequest.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateRequest.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateResponse.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpgradeRequest.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyEvent.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecution.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecutionRequest.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceId.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecret.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecretUpload.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointCredentials.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointTransport.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerOpsTools.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyBlueprint.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprint.java with 57% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyBlueprintList.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintList.java with 69% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployedTenant.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployedTenantList.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployedTenantList.java with 69% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployment.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeploymentExt.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployedTenant.java with 65% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeploymentHelm.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/EcdAppComponent.java with 67% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeploymentList.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecretList.java with 64% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyErrorCause.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyErrorCause.java with 66% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyEvent.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyEventList.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyEventList.java with 69% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecution.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecutionList.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecutionList.java with 69% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecutionRequest.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeId.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeId.java with 84% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeIdList.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeIdList.java with 69% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstance.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstance.java with 73% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstanceId.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintContent.java with 72% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstanceIdList.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceIdList.java with 68% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyNodeInstanceList.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceList.java with 69% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyPlugin.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyBlueprintUpload.java with 54% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyPluginList.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentList.java with 82% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifySecret.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyTenant.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyTenant.java with 73% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyTenantList.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyTenantList.java with 69% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/ServiceRefCfyList.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceGroupByResults.java with 67% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulDatacenter.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulDatacenter.java with 94% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulDeploymentHealth.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulHealthServiceRegistration.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulHealthServiceRegistration.java with 97% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulNodeInfo.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulNodeInfo.java with 96% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceCatalogItem.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceHealth.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceHealth.java with 79% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceHealthHistory.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceHealthHistory.java with 95% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceInfo.java [moved from ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ConsulServiceInfo.java with 95% similarity]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentInput.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentRequest.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/DeploymentRequestObject.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/InventoryDeploymentRequest.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/Blueprint.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/Service.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceComponentRequest.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRef.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRefList.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRequest.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceType.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeQueryParams.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeRequest.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeServiceMap.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummary.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummaryList.java [new file with mode: 0644]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/CloudifyClient.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/CloudifyRestClientImpl.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ConsulClient.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/ConsulRestClientImpl.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClient.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClientImpl.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/InventoryClient.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/RestClientBase.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/rest/RestInventoryClientImpl.java
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointService.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointServiceImpl.java [deleted file]
ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/util/DashboardProperties.java
ccsdk-app-common/src/test/java/org/onap/ccsdk/api/controller/NbApiControllerTest.java [new file with mode: 0644]
ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/CloudifyControllerTest.java
ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/CommonApiControllerTest.java [deleted file]
ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/ConsulControllerTest.java
ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/DeploymentHandlerControllerTest.java
ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/InventoryControllerTest.java
ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/model/ControllerOpsToolsTest.java [deleted file]
ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/CloudifyRestClientImplTest.java
ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/ConsulRestClientImplTest.java
ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/DeploymentHandlerClientImplTest.java
ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/rest/RestInventoryClientImplTest.java
ccsdk-app-os/create_table.sql
ccsdk-app-os/pom.xml
ccsdk-app-os/src/main/java/org/onap/portalapp/conf/ExternalAppConfig.java
ccsdk-app-os/src/main/java/org/onap/portalapp/conf/ExternalAppInitializer.java
ccsdk-app-os/src/main/java/org/onap/portalapp/conf/HibernateMappingLocations.java
ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthenticationInterceptor.java [new file with mode: 0644]
ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthorizationInterceptor.java [new file with mode: 0644]
ccsdk-app-os/src/main/java/org/onap/portalapp/login/LoginStrategyImpl.java
ccsdk-app-os/src/main/resources/portal.properties
ccsdk-app-os/src/main/resources/swagger.json
ccsdk-app-os/src/main/webapp/WEB-INF/conf/dashboard.properties
ccsdk-app-os/src/main/webapp/WEB-INF/jsp/login_external.jsp
ccsdk-app-os/src/main/webapp/WEB-INF/jsp/signup.jsp [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/WEB-INF/oom-app-definitions.xml [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/WEB-INF/oom-app.hbm.xml [moved from ccsdk-app-overlay/src/main/webapp/WEB-INF/oom-app.hbm.xml with 100% similarity]
ccsdk-app-os/src/main/webapp/api-specs.html
ccsdk-app-os/src/main/webapp/app/ccsdk/home/api_view.html [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/app/ccsdk/home/app-router.js [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions-view-controller.js [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions_view.html [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/app/ccsdk/home/oom-style.css [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/app/ccsdk/home/oom_spa.html [moved from ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_spa.html with 80% similarity]
ccsdk-app-os/src/main/webapp/app/ccsdk/images/ecomp.png [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_16x16.ico [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_32x32.ico [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_logo_2257x496.png [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/app/fusion/external/ds2/css/digital-ng-library/ecomp-ionicons.css
ccsdk-app-os/src/main/webapp/index.jsp [new file with mode: 0644]
ccsdk-app-os/src/main/webapp/manifest.jsp [new file with mode: 0644]
ccsdk-app-overlay/pom.xml
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-controllers.js [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-service.js [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_popups.html [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_table.html [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment-controllers.js
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment-service.js
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment_popups.html
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/deployment_table.html
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/execution-service.js
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-service.js [new file with mode: 0644]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-table-controller.js [new file with mode: 0644]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin_table.html [moved from ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/controller_table.html with 57% similarity]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca-table-controller.js [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca_table.html [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/consul/node_table.html
ccsdk-app-overlay/src/main/webapp/app/ccsdk/consul/service_health_table.html
ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/angular-local-storage.js [new file with mode: 0644]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.css [new file with mode: 0644]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.js [new file with mode: 0644]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/api_doc.html [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/appDS2.js
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/controller-service.js
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/ecd_popup_templates.html [moved from ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_popup_templates.html with 99% similarity]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions-view-controller.js [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions_view.html [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/http-interceptor.js [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-instances-controller.js [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-router.js [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-style.css [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_instances_popup.html [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-controller.js [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-directive.js [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-style.css [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree_view.html [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/blueprint-controllers.js
ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/blueprint-service.js
ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/deployment-controllers.js [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/deployment-service.js
ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/execution-service.js
ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_blueprint_popups.html
ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_blueprint_table.html
ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_deployment_popups.html
ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_deployment_table.html [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_execution_popups.html
ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/dbcl_view.html [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs-view-controller.js [deleted file]
ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs_view.html [deleted file]
pom.xml
version.properties

index 2c3297b..875d9ea 100644 (file)
@@ -6,12 +6,12 @@
        <parent>
                <groupId>org.onap.ccsdk.dashboard</groupId>
                <artifactId>ccsdk-app-parent</artifactId>
-               <version>1.3.2-SNAPSHOT</version>
+               <version>1.4.0-SNAPSHOT</version>
        </parent>
 
        <groupId>org.onap.ccsdk.dashboard</groupId>
        <artifactId>ccsdk-app-common</artifactId>
-       <version>1.3.2-SNAPSHOT</version>
+       <version>1.4.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <name>ONAP Operations Manager Dashboard common</name>
        <description>CCSDK Dashboard common Java code</description>
@@ -76,7 +76,6 @@
 
        <build>
                <plugins>
-
                        <!-- Compile to Java 1.8 class output format -->
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
@@ -87,7 +86,6 @@
                                        <target>1.8</target>
                                </configuration>
                        </plugin>
-
                        <!-- Put version into jar also -->
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                        </archive>
                                </configuration>
                        </plugin>
-
                        <!-- Generate javadoc jar; see profile for Java 8 -->
+                       <!--
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-javadoc-plugin</artifactId>
                                        </execution>
                                </executions>
                        </plugin>
-
+                       -->
                        <!-- Generate source jar -->
+                       <!--  
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-source-plugin</artifactId>
                                        </execution>
                                </executions>
                        </plugin>
+                       -->
                        <!-- jacoco -->
                        <plugin>
                                <groupId>org.jacoco</groupId>
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/ApiBaseController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/ApiBaseController.java
new file mode 100644 (file)
index 0000000..ec30b92
--- /dev/null
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.ccsdk.api.controller;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.onap.ccsdk.dashboard.util.DashboardProperties;
+import org.onap.portalsdk.core.controller.UnRestrictedBaseController;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+
+public class ApiBaseController extends UnRestrictedBaseController {
+
+    /**
+     * Application name
+     */
+    protected static final String APP_NAME = "ecd-app";
+
+    /**
+     * EELF-approved format
+     */
+    protected static final DateFormat logDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
+
+    /**
+     * Query parameter for desired page number
+     */
+    protected static final String PAGE_NUM_QUERY_PARAM = "page";
+
+    /**
+     * Query parameter for desired items per page
+     */
+    protected static final String PAGE_SIZE_QUERY_PARAM = "size";
+
+    /**
+     * For general use in these methods and subclasses
+     */
+    protected final ObjectMapper objectMapper = new ObjectMapper();
+
+    /**
+     * Application properties - NOT available to constructor.
+     */
+    @Autowired
+    protected DashboardProperties appProperties;
+
+    /**
+     * Hello Spring, here's your no-arg constructor.
+     */
+    public ApiBaseController() {
+        // Do not serialize null values
+        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+        // Register Jdk8Module() for Stream and Optional types
+        objectMapper.registerModule(new Jdk8Module());
+    }
+
+    /**
+     * Access method for subclasses.
+     * 
+     * @return DbcappProperties object that was autowired by Spring.
+     */
+    protected DashboardProperties getAppProperties() {
+        return appProperties;
+    }
+
+    /**
+     * Gets the requested page number from a query parameter in the
+     * HttpServletRequest. Defaults to 1, which is useful to allow manual testing of
+     * endpoints without supplying those pesky parameters.
+     * 
+     * @param request HttpServletRequest
+     * @return Value of query parameter {@link #PAGE_NUM_QUERY_PARAM}; 1 if not
+     *         found.
+     */
+    protected int getRequestPageNumber(HttpServletRequest request) {
+        int pageNum = 1;
+        String param = request.getParameter(PAGE_NUM_QUERY_PARAM);
+        if (param != null)
+            pageNum = Integer.parseInt(param);
+        return pageNum;
+    }
+
+    /**
+     * Gets the requested page size from a query parameter in the
+     * HttpServletRequest. Defaults to 50, which is useful to allow manual testing
+     * of endpoints without supplying those pesky parameters.
+     * 
+     * @param request HttpServletRequest
+     * @return Value of query parameter {@link #PAGE_SIZE_QUERY_PARAM}; 50 if not
+     *         found.
+     */
+    protected int getRequestPageSize(HttpServletRequest request) {
+        int pageSize = 25;
+        String param = request.getParameter(PAGE_SIZE_QUERY_PARAM);
+        if (param != null)
+            pageSize = Integer.parseInt(param);
+        return pageSize;
+    }
+
+    /**
+     * Gets the items for the specified page from the specified list.
+     * 
+     * @param pageNum  Page number requested by user, indexed from 1
+     * @param pageSize Number of items per page
+     * @param itemList List of items to adjust
+     * @return List of items; empty list if from==to
+     */
+    @SuppressWarnings("rawtypes")
+    protected static List getPageOfList(final int pageNum, final int pageSize, final List itemList) {
+        int firstIndexOnThisPage = pageSize * (pageNum - 1);
+        int firstIndexOnNextPage = pageSize * pageNum;
+        int fromIndex = firstIndexOnThisPage < itemList.size() ? firstIndexOnThisPage : itemList.size();
+        int toIndex = firstIndexOnNextPage < itemList.size() ? firstIndexOnNextPage : itemList.size();
+        return itemList.subList(fromIndex, toIndex);
+    }
+    
+    @Override
+    public boolean isRESTfulCall() {
+        return true;
+    }
+}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/NbApiController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/NbApiController.java
new file mode 100644 (file)
index 0000000..525711d
--- /dev/null
@@ -0,0 +1,1394 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+
+package org.onap.ccsdk.api.controller;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.http.HttpStatus;
+import org.json.JSONObject;
+import org.onap.aaf.cadi.CadiWrap;
+import org.onap.ccsdk.dashboard.exceptions.BadRequestException;
+import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException;
+import org.onap.ccsdk.dashboard.exceptions.DownstreamException;
+import org.onap.ccsdk.dashboard.exceptions.ServerErrorException;
+import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException;
+import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException;
+import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeAlreadyDeactivatedException;
+import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException;
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+import org.onap.ccsdk.dashboard.model.RestResponseError;
+import org.onap.ccsdk.dashboard.model.RestResponsePage;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList;
+import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentInput;
+import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest;
+import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResource;
+import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResourceLinks;
+import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse;
+import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponseLinks;
+import org.onap.ccsdk.dashboard.model.inventory.Blueprint;
+import org.onap.ccsdk.dashboard.model.inventory.BlueprintInput;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceRef;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceType;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeServiceMap;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeUploadRequest;
+import org.onap.ccsdk.dashboard.rest.CloudifyClient;
+import org.onap.ccsdk.dashboard.rest.ConsulClient;
+import org.onap.ccsdk.dashboard.rest.DeploymentHandlerClient;
+import org.onap.ccsdk.dashboard.rest.InventoryClient;
+import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.onap.portalsdk.core.objectcache.AbstractCacheManager;
+import org.onap.portalsdk.core.util.SystemProperties;
+import org.slf4j.MDC;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.http.HttpHeaders;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.HttpStatusCodeException;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+
+@RestController
+@RequestMapping("/nb-api/v2")
+public class NbApiController extends ApiBaseController {
+    private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(NbApiController.class);
+
+    private static final String DEPLOYMENTS_PATH = "deployments";
+    private static final String SERVICE_TYPES_PATH = "blueprints";
+    private static final String EXECUTIONS_PATH = "executions";
+    private static final String TENANTS_PATH = "tenants";
+    private static final String SERVICE_HEALTH_PATH = "health";
+
+    @Autowired
+    InventoryClient inventoryClient;
+
+    @Autowired
+    DeploymentHandlerClient deploymentHandlerClient;
+
+    @Autowired
+    CloudifyClient cloudifyClient;
+
+    @Autowired
+    ConsulClient consulClient;
+
+    @Autowired
+    ApplicationEventPublisher eventPub;
+
+    private AbstractCacheManager cacheManager;
+
+    @Autowired
+    public void setCacheManager(AbstractCacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+    }
+
+    public AbstractCacheManager getCacheManager() {
+        return cacheManager;
+    }
+
+    /**
+     * Enum for selecting an item type.
+     */
+    public enum InventoryDataItem {
+        DEPLOYMENTS, BLUEPRINTS, SERVICES_GROUPBY;
+    }
+
+    private static Date begin, end;
+
+    /**
+     * get the tenants list
+     * 
+     * @param request HttpServletRequest
+     * @return List of CloudifyDeployment objects
+     */
+    @SuppressWarnings("rawtypes")
+    @RequestMapping(
+        value = {TENANTS_PATH},
+        method = RequestMethod.GET,
+        produces = "application/json")
+    @ResponseBody
+    public String getTenants(HttpServletRequest request) throws Exception {
+        preLogAudit(request);
+        List itemList = cloudifyClient.getTenants().items;
+        final int totalItems = itemList.size();
+        final int pageSize = 20;
+        final int pageNum = 1;
+        final int pageCount = (int) Math.ceil((double) totalItems / pageSize);
+        if (totalItems > pageSize)
+            itemList = getPageOfList(pageNum, pageSize, itemList);
+        RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList);
+        String outboundJson = objectMapper.writeValueAsString(model);
+        return outboundJson;
+    }
+
+    private boolean isAuthorized(HttpServletRequest request, String component) {
+        boolean auth = true;
+        return auth;
+    }
+
+    @RequestMapping(
+        value = {SERVICE_TYPES_PATH},
+        method = RequestMethod.POST,
+        produces = "application/json")
+    public String createBlueprint(HttpServletRequest request, HttpServletResponse response,
+        @RequestBody ServiceTypeUploadRequest serviceTypeUplReq,
+        ServletUriComponentsBuilder uriBuilder) throws Exception {
+        preLogAudit(request);
+        String json = null;
+        try {
+            Blueprint.parse(serviceTypeUplReq.getBlueprintTemplate());
+
+            if (serviceTypeUplReq.component == null || serviceTypeUplReq.component.isEmpty()) {
+                json = objectMapper.writeValueAsString(
+                    new RestResponseError("Component name missing in blueprint request body"));
+                logger.error(EELFLoggerDelegate.errorLogger,
+                    "Component name missing in blueprint request body");
+                return json;
+            }
+
+            if (!isAuthorized(request, serviceTypeUplReq.component)) {
+                response.setStatus(HttpStatus.SC_FORBIDDEN);
+                json = objectMapper.writeValueAsString(
+                    new RestResponseError("Un-authorized to perform this operation"));
+                return json;
+            }
+
+            Collection<String> serviceIds = new ArrayList<String>();
+            Collection<String> vnfTypes = new ArrayList<String>();
+            Collection<String> serviceLocations = new ArrayList<String>();
+            Optional<String> asdcServiceId = null;
+            Optional<String> asdcResourceId = null;
+            Optional<String> asdcServiceURL = null;
+
+            ServiceTypeRequest invSrvcTypeReq =
+                new ServiceTypeRequest(serviceTypeUplReq.owner, serviceTypeUplReq.typeName,
+                    serviceTypeUplReq.typeVersion, serviceTypeUplReq.blueprintTemplate,
+                    serviceTypeUplReq.application, serviceTypeUplReq.component, serviceIds,
+                    vnfTypes, serviceLocations, asdcServiceId, asdcResourceId, asdcServiceURL);
+            ServiceType apiResponse = inventoryClient.addServiceType(invSrvcTypeReq);
+            json = objectMapper.writeValueAsString(apiResponse);
+            String uri = request.getRequestURI();
+            if (uri != null) {
+            String uri_all = uriBuilder.replacePath(uri).build().toUriString();
+            String uri_self =
+                uriBuilder.path("/" + apiResponse.getTypeId().get()).build().toUriString();
+            StringBuffer linkHeader = new StringBuffer();
+            String linkStr_all = "<" + uri_all + ">; rel=\"" + "current" + "\"";
+            String linkStr_self = "<" + uri_self + ">; rel=\"" + "self" + "\"";
+            linkHeader.append(linkStr_self);
+            if (linkHeader.length() > 0) {
+                linkHeader.append(", ");
+            }
+            linkHeader.append(linkStr_all);
+            response.addHeader("Link", linkHeader.toString());
+            }
+        } catch (BlueprintParseException e) {
+            response.setStatus(HttpStatus.SC_BAD_REQUEST);
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "DCAE Inventory");
+            MDC.put("TargetServiceName", "DCAE Inventory");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Updating service type failed!");
+            logger.error(EELFLoggerDelegate.errorLogger,
+                "updateServiceTypeBlueprint caught exception");
+            json = objectMapper
+                .writeValueAsString(new RestResponseError("Invalid blueprint format.", e));
+        } catch (HttpStatusCodeException e) {
+            response.setStatus(HttpStatus.SC_BAD_GATEWAY);
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "DCAE Inventory");
+            MDC.put("TargetServiceName", "DCAE Inventory");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Updating service type failed!");
+            logger.error(EELFLoggerDelegate.errorLogger,
+                "updateServiceTypeBlueprint caught exception");
+            json =
+                objectMapper.writeValueAsString(new RestResponseError(e.getResponseBodyAsString()));
+        } catch (Throwable t) {
+            response.setStatus(HttpStatus.SC_BAD_REQUEST);
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "DCAE Inventory");
+            MDC.put("TargetServiceName", "DCAE Inventory");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Updating service type failed!");
+            logger.error(EELFLoggerDelegate.errorLogger,
+                "updateServiceTypeBlueprint caught exception");
+            json = objectMapper
+                .writeValueAsString(new RestResponseError("updateServiceTypeBlueprint failed", t));
+        } finally {
+            postLogAudit(request);
+        }
+        return json;
+    }
+
+    @SuppressWarnings("unchecked")
+    @RequestMapping(
+        value = {SERVICE_TYPES_PATH},
+        method = RequestMethod.GET,
+        produces = "application/json")
+    public String getBlueprintsByPage(HttpServletRequest request,
+        @RequestParam(value = "page", required = false) Integer page,
+        @RequestParam(value = "size", required = false) Integer size,
+        ServletUriComponentsBuilder uriBuilder, HttpServletResponse response) {
+        preLogAudit(request);
+        String json = null;
+        if (page == null || page == 0) {
+            page = 1;
+        }
+        if (size == null) {
+            size = 25;
+        }
+        int pageNum = page;
+        int totalItems = 0;
+        List itemList = null;
+        try {
+            itemList = getItemListForPageWrapper(request, InventoryDataItem.BLUEPRINTS);
+            // Shrink if needed
+            if (itemList != null) {
+                totalItems = itemList.size();
+            }
+            final int pageCount = (int) Math.ceil((double) totalItems / size);
+            if (totalItems > size)
+                itemList = getPageOfList(pageNum, size, itemList);
+
+            RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList);
+            json = objectMapper.writeValueAsString(model);
+
+            try {
+            uriBuilder = ServletUriComponentsBuilder.fromCurrentRequest();
+            eventPub.publishEvent(new PaginatedResultsRetrievedEvent<String>(String.class,
+                uriBuilder, response, page, pageCount, size));
+            } catch (Exception e) {
+                // skip exception
+            }
+        } catch (Exception e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Getting page of blueprints items failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getBlueprintsByPage caught exception");
+            RestResponseError result = null;
+            if (e instanceof HttpStatusCodeException)
+                result =
+                new RestResponseError(((HttpStatusCodeException) e).getResponseBodyAsString());
+            else
+                result = new RestResponseError("Failed to get blueprints", e);
+            try {
+                json = objectMapper.writeValueAsString(result);
+            } catch (JsonProcessingException jpe) {
+                // Should never, ever happen
+                json = "{ \"error\" : \"" + jpe.toString() + "\"}";
+            }
+            return json;
+        } finally {
+            postLogAudit(request);
+        }
+        return json;
+    }
+
+    private List getItemListForPageWrapper(HttpServletRequest request, InventoryDataItem option) {
+        Set<String> userRoleSet = (Set<String>) request.getAttribute("userRoles");
+        Set<String> userApps = (Set<String>) request.getAttribute("userApps");
+        String sort = request.getParameter("sort");
+
+        Predicate<String> adminPred =
+            p -> p.contains("System_Administrator") || p.contains("Write_Access");
+
+            Predicate<String> ecompSuperPred =
+                p -> p.contains("ECOMPC_WRITE") || p.contains("ECOMPC_READ");
+
+                ReadWriteLock lock = new ReentrantReadWriteLock();
+                List itemList = null;
+                try {
+                    lock.readLock().lock();
+                    itemList = (List<ServiceTypeSummary>) getCacheManager().getObject("dcae-service-types");
+                    lock.readLock().unlock();
+                    if (itemList == null) {
+                        ServiceTypeQueryParams serviceQueryParams = null;
+                        itemList = inventoryClient.getServiceTypes().collect(Collectors.toList());
+                    }
+                    if (userRoleSet != null) {
+                        if (userRoleSet.stream().noneMatch(adminPred)) {
+                            if (userRoleSet.stream().noneMatch(ecompSuperPred)) {
+                                itemList = (List<ServiceTypeSummary>) itemList.stream()
+                                    .filter(s -> userApps.stream()
+                                        .anyMatch(appFilter -> (((ServiceTypeSummary) s).getComponent() != null
+                                        && ((ServiceTypeSummary) s).getComponent()
+                                        .equalsIgnoreCase(appFilter))))
+                                    .collect(Collectors.<ServiceTypeSummary>toList());
+                            } else {
+                                Predicate<ServiceTypeSummary> appFilter =
+                                    p -> p.getComponent() != null && !p.getComponent().equalsIgnoreCase("dcae");
+                                    itemList = (List<ServiceTypeSummary>) itemList.stream().filter(appFilter)
+                                        .collect(Collectors.toList());
+                            }
+                        }
+                    }
+                    // Handle request filter object
+                    String filters = request.getParameter("filters");
+                    if (filters != null) {
+                        JSONObject filterJson = new JSONObject(filters);
+
+                        if (filterJson.has("owner")) {
+                            String ownFilter = filterJson.getString("owner");
+                            Predicate<ServiceTypeSummary> ownPred =
+                                p -> p.getOwner() != null && p.getOwner().contains(ownFilter);
+                                itemList = (List<ServiceTypeSummary>) itemList.stream().filter(ownPred)
+                                    .collect(Collectors.toList());
+                        }
+
+                        if (filterJson.has("name")) {
+                            String bpNameFilter = filterJson.getString("name");
+                            Predicate<ServiceTypeSummary> bpNamePred =
+                                p -> p.getTypeName() != null && p.getTypeName().contains(bpNameFilter);
+                                itemList = (List<ServiceTypeSummary>) itemList.stream().filter(bpNamePred)
+                                    .collect(Collectors.toList());
+                        }
+
+                        if (filterJson.has("id")) {
+                            String bpIdFilter = filterJson.getString("id");
+                            Predicate<ServiceTypeSummary> bpIdPred =
+                                p -> p.getTypeId().get().contains(bpIdFilter);
+                                itemList = (List<ServiceTypeSummary>) itemList.stream().filter(bpIdPred)
+                                    .collect(Collectors.toList());
+                        }
+                    }
+                    if (sort != null) {
+                        if (sort.equals("owner")) {
+                            ((List<ServiceTypeSummary>) itemList).sort((ServiceTypeSummary o1,
+                                ServiceTypeSummary o2) -> o1.getOwner().compareTo(o2.getOwner()));
+                        } else if (sort.equals("typeId")) {
+                            ((List<ServiceTypeSummary>) itemList)
+                            .sort((ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getTypeId().get()
+                                .compareTo(o2.getTypeId().get()));
+                        } else if (sort.equals("typeName")) {
+                            ((List<ServiceTypeSummary>) itemList).sort((ServiceTypeSummary o1,
+                                ServiceTypeSummary o2) -> o1.getTypeName().compareTo(o2.getTypeName()));
+                        } else if (sort.equals("typeVersion")) {
+                            ((List<ServiceTypeSummary>) itemList)
+                            .sort((ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getTypeVersion()
+                                .compareTo(o2.getTypeVersion()));
+                        } else if (sort.equals("created")) {
+                            ((List<ServiceTypeSummary>) itemList)
+                            .sort((ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getCreated()
+                                .get().compareTo(o2.getCreated().get()));
+                        }
+                    }
+                } catch (Exception e) {
+                    throw e;
+                } finally {
+                    postLogAudit(request);
+                }
+                return itemList;
+    }
+
+    @RequestMapping(
+        value = {DEPLOYMENTS_PATH + "/{deploymentId}"},
+        method = RequestMethod.GET,
+        produces = "application/json")
+    public String getDeployment(@PathVariable("deploymentId") String deploymentId,
+        HttpServletRequest request) {
+        preLogAudit(request);
+        String json = null;
+        try {
+            List<CloudifyDeployment> items = cloudifyClient.getDeployment(deploymentId).items;
+            json = objectMapper.writeValueAsString(items);
+        } catch (Exception gen) {
+            logger.error(EELFLoggerDelegate.errorLogger, "getDeployment caught exception");
+            RestResponseError result = null;
+            if (gen instanceof HttpStatusCodeException)
+                result = new RestResponseError(
+                    ((HttpStatusCodeException) gen).getResponseBodyAsString());
+            else
+                result = new RestResponseError("Failed to get deployment", gen);
+            try {
+                json = objectMapper.writeValueAsString(result);
+            } catch (JsonProcessingException jpe) {
+                // Should never, ever happen
+                json = "{ \"error\" : \"" + jpe.toString() + "\"}";
+            }
+        } finally {
+            postLogAudit(request);
+        }
+        return json;
+    }
+
+    @SuppressWarnings("unchecked")
+    @RequestMapping(
+        value = {DEPLOYMENTS_PATH},
+        method = RequestMethod.GET,
+        produces = "application/json")
+    public String getDeploymentsByPage(HttpServletRequest request,
+        @RequestParam(value = "page", required = false) Integer page,
+        @RequestParam(value = "size", required = false) Integer size,
+        ServletUriComponentsBuilder uriBuilder, HttpServletResponse response) {
+        preLogAudit(request);
+        String outboundJson = null;
+        if (page == null || page == 0) {
+            page = 1;
+        }
+        if (size == null) {
+            size = 25;
+        }
+        int pageNum = page;
+        int totalItems = 0;
+        List<CloudifyDeployment> itemList = null;
+        try {
+            itemList = cloudifyClient.getDeploymentsWithFilter(request);
+
+            // Shrink if needed
+            if (itemList != null) {
+                totalItems = itemList.size();
+            }
+            final int pageCount = (int) Math.ceil((double) totalItems / size);
+            if (totalItems > size) {
+                itemList = getPageOfList(pageNum, size, itemList);
+            }
+            RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList);
+            outboundJson = objectMapper.writeValueAsString(model);
+            try {
+                uriBuilder = ServletUriComponentsBuilder.fromCurrentRequest();
+                eventPub.publishEvent(new PaginatedResultsRetrievedEvent<String>(String.class,
+                    uriBuilder, response, page, pageCount, size));
+            } catch (Exception e) {
+                // skip the pagination links logic
+            }
+            return outboundJson;
+        } catch (Exception e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Getting page of deployments items failed!");
+            logger.error(EELFLoggerDelegate.errorLogger,
+                "getAllDeploymentsByPage caught exception");
+            RestResponseError result = null;
+            if (e instanceof HttpStatusCodeException)
+                result =
+                new RestResponseError(((HttpStatusCodeException) e).getResponseBodyAsString());
+            else
+                result = new RestResponseError("Failed to get deployments", e);
+            try {
+                outboundJson = objectMapper.writeValueAsString(result);
+            } catch (JsonProcessingException jpe) {
+                // Should never, ever happen
+                outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}";
+            }
+            return outboundJson;
+        } finally {
+            postLogAudit(request);
+        }
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    private ServiceTypeSummary getBlueprintItem(String searchBy, Optional<Integer> version,
+        String typeId) throws Exception {
+        ServiceTypeQueryParams serviceQueryParams = null;
+        ServiceTypeSummary item = null;
+        if (version.isPresent()) {
+            serviceQueryParams =
+                new ServiceTypeQueryParams.Builder().typeName(searchBy).onlyLatest(false).build();
+        } else {
+            serviceQueryParams = new ServiceTypeQueryParams.Builder().typeName(searchBy).build();
+        }
+
+        List itemList =
+            inventoryClient.getServiceTypes(serviceQueryParams).collect(Collectors.toList());
+
+        if (version.isPresent()) {
+            itemList = (List) itemList.stream()
+                .filter(s -> ((ServiceTypeSummary) s).contains(version.get().toString()))
+                .collect(Collectors.toList());
+        }
+        if (typeId != null && typeId.equals("typeId")) {
+            item = (ServiceTypeSummary) ((List) itemList).get(0);
+        }
+        return item;
+    }
+
+    /**
+     * Query inputs used to create a deployment
+     * 
+     * @param deploymentId
+     * @param tenant
+     * @param request
+     * @return
+     * @throws Exception
+     */
+    @RequestMapping(
+        value = {DEPLOYMENTS_PATH + "/{deploymentId}/inputs"},
+        method = RequestMethod.GET,
+        produces = "application/json")
+    public String getDeploymentInputs(@PathVariable("deploymentId") String deploymentId,
+        @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request)
+            throws Exception {
+        preLogAudit(request);
+        ECTransportModel result = null;
+        String json = "";
+        try {
+            if (tenant == null) {
+                throw new Exception("tenant name is missing");
+            }
+            List<CloudifyDeployment> response =
+                cloudifyClient.getDeploymentInputs(deploymentId, tenant).items;
+            json = objectMapper.writeValueAsString(response);
+        } catch (HttpStatusCodeException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API controller");
+            MDC.put("TargetServiceName", "API controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription",
+                "Getting executions for deployment " + deploymentId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger,
+                "getExecutionByIdAndDeploymentId caught exception");
+            result = new RestResponseError(e.getResponseBodyAsString());
+            json = objectMapper.writeValueAsString(result);
+        } catch (Throwable t) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API controller");
+            MDC.put("TargetServiceName", "API controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription",
+                "Getting executions for deployment " + deploymentId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger,
+                "getExecutionByIdAndDeploymentId caught exception");
+            result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t);
+            json = objectMapper.writeValueAsString(result);
+        } finally {
+            postLogAudit(request);
+        }
+        return json;
+    }
+
+    /**
+     * Create an upgrade/rollback workflow execution for a deployment.
+     * 
+     * @param request HttpServletRequest
+     * @param execution Execution model
+     * @return Information about the execution
+     * @throws Exception on serialization failure
+     */
+    @RequestMapping(
+        value = {DEPLOYMENTS_PATH + "/{deploymentId}"},
+        method = RequestMethod.PUT,
+        produces = "application/json")
+    public String modifyDeployment(@PathVariable("deploymentId") String deploymentId,
+        HttpServletRequest request, InputStream upgParams) throws Exception {
+        preLogAudit(request);
+        ECTransportModel result = null;
+        try {
+            String nodeInstId = "";
+            Map<String, Object> parameters =
+                objectMapper.readValue(upgParams, new TypeReference<Map<String, Object>>() {});
+            String tenant = (String) parameters.get("tenant");
+            String workflow = (String) parameters.get("workflow");
+            parameters.remove("tenant");
+            parameters.remove("workflow");
+            // get the node instance ID for the deployment
+            CloudifyNodeInstanceIdList nodeInstList =
+                cloudifyClient.getNodeInstanceId(deploymentId, tenant);
+            if (nodeInstList != null) {
+                nodeInstId = nodeInstList.items.get(0).id;
+            }
+            parameters.put("node_instance_id", nodeInstId);
+            if (workflow.equals("upgrade")) {
+                String repo_user = cloudifyClient.getSecret("controller_helm_user", tenant).value;
+                String repo_user_password =
+                    cloudifyClient.getSecret("controller_helm_password", tenant).value;
+                parameters.put("repo_user", repo_user);
+                parameters.put("repo_user_password", repo_user_password);
+            }
+            CloudifyExecutionRequest execution = new CloudifyExecutionRequest(deploymentId,
+                workflow, false, false, tenant, parameters);
+            result = cloudifyClient.startExecution(execution);
+        } catch (HttpStatusCodeException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API controller");
+            MDC.put("TargetServiceName", "API controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Updating deployment failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception");
+            result = new RestResponseError(e.getResponseBodyAsString());
+        } catch (Throwable t) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API controller");
+            MDC.put("TargetServiceName", "API controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Updating Deployment failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception");
+            result = new RestResponseError("updateDeployment failed", t);
+        } finally {
+            postLogAudit(request);
+        }
+        return objectMapper.writeValueAsString(result);
+    }
+
+    @RequestMapping(
+        value = {SERVICE_TYPES_PATH + "/{typeid}" + "/deployments"},
+        method = RequestMethod.GET,
+        produces = "application/json")
+    public String getServicesForType(HttpServletRequest request,
+        @PathVariable("typeid") String typeId) throws Exception {
+        preLogAudit(request);
+        List<ServiceTypeServiceMap> result = new ArrayList<ServiceTypeServiceMap>();
+        ServiceQueryParams qryParams = new ServiceQueryParams.Builder().typeId(typeId).build();
+        ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams);
+        ServiceTypeServiceMap srvcMap = new ServiceTypeServiceMap(typeId, srvcRefs);
+        result.add(srvcMap);
+        return objectMapper.writeValueAsString(result);
+    }
+
+    private static void mergeInputData(Map<String, Object> bpInputs, Map<String, Object> dataSet,
+        String key, Object val) {
+        Object keyVal = dataSet.get(key);
+        if (keyVal != null) {
+            bpInputs.put(key, keyVal);
+        } else {
+            Object bpInput = ((BlueprintInput) val).getDefaultValue();
+            if (bpInput != null) {
+                bpInputs.put(key, bpInput);
+            } else {
+                bpInputs.put(key, "");
+            }
+        }
+    }
+
+    private static void translateInputData(Map<String, Object> dataSet, String key, Object val) {
+        try {
+            if (val instanceof java.lang.String) {
+                int numericVal = Integer.parseInt((String) val);
+                dataSet.put(key, numericVal);
+            } else {
+                dataSet.put(key, val);
+            }
+        } catch (NumberFormatException ne) {
+            dataSet.put(key, val);
+        } catch (Exception e) {
+            dataSet.put(key, val);
+        }
+    }
+
+    @RequestMapping(
+        value = {DEPLOYMENTS_PATH},
+        method = RequestMethod.POST,
+        produces = "application/json")
+    public String createDeployment(HttpServletRequest request, HttpServletResponse response,
+        @RequestBody DeploymentInput deploymentRequestObject) throws Exception {
+        preLogAudit(request);
+        String json = null;
+        StringBuffer status = new StringBuffer();
+        Optional<Integer> bpVersion = null;
+        String srvcTypeId = null;
+        ServiceTypeSummary bpSummItem = null;
+        ServiceType bpItem = null;
+        String bpName = deploymentRequestObject.getBlueprintName();
+        String cName = deploymentRequestObject.getComponent();
+        String tag = deploymentRequestObject.getTag();
+        String depName = cName + "_" + tag;
+        Map<String, BlueprintInput> bpInputDefs = null;
+
+        if (cName == null || cName.isEmpty()) {
+            json = objectMapper.writeValueAsString(
+                new RestResponseError("Component name missing in deployment request body"));
+            logger.error(EELFLoggerDelegate.errorLogger,
+                "Component name missing in deployment request body");
+            return json;
+        }
+
+        if (!isAuthorized(request, cName)) {
+            response.setStatus(HttpStatus.SC_FORBIDDEN);
+            json = objectMapper.writeValueAsString(
+                new RestResponseError("Un-authorized to perform this operation"));
+            return json;
+        }
+
+        if (deploymentRequestObject.getBlueprintVersion().isPresent()) {
+            bpVersion = deploymentRequestObject.getBlueprintVersion();
+        }
+        if (deploymentRequestObject.getBlueprintId().isPresent()) {
+            srvcTypeId = deploymentRequestObject.getBlueprintId().get();
+        }
+        if (srvcTypeId == null) {
+            // get the serviceTypeId from inventory using the blueprint name
+            try {
+                bpSummItem = getBlueprintItem(bpName, bpVersion, "typeId");
+                srvcTypeId = bpSummItem.getTypeId().get();
+                bpItem = inventoryClient.getServiceType(srvcTypeId).get();
+            } catch (Exception ex) {
+                MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+                MDC.put("TargetEntity", "API controller");
+                MDC.put("TargetServiceName", "API controller");
+                MDC.put("ErrorCode", "300");
+                MDC.put("ErrorCategory", "ERROR");
+                MDC.put("ErrorDescription", "Getting blueprint ID failed!");
+                logger.error(EELFLoggerDelegate.errorLogger,
+                    "getItemListForPageWrapper caught exception");
+                RestResponseError result = null;
+                if (ex instanceof HttpStatusCodeException)
+                    result = new RestResponseError(
+                        ((HttpStatusCodeException) ex).getResponseBodyAsString());
+                else
+                    result = new RestResponseError("Failed to get blueprint", ex);
+                try {
+                    json = objectMapper.writeValueAsString(result);
+                } catch (JsonProcessingException jpe) {
+                    // Should never, ever happen
+                    json = "{ \"error\" : \"" + jpe.toString() + "\"}";
+                }
+                return json;
+            } finally {
+                postLogAudit(request);
+            }
+        } else {
+            try {
+                bpItem = inventoryClient.getServiceType(srvcTypeId).get();
+            } catch (Exception ex) {
+                MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+                MDC.put("TargetEntity", "API controller");
+                MDC.put("TargetServiceName", "API controller");
+                MDC.put("ErrorCode", "300");
+                MDC.put("ErrorCategory", "ERROR");
+                MDC.put("ErrorDescription", "Getting blueprint failed!");
+                logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception");
+                RestResponseError result = null;
+                if (ex instanceof HttpStatusCodeException)
+                    result = new RestResponseError(
+                        ((HttpStatusCodeException) ex).getResponseBodyAsString());
+                else
+                    result = new RestResponseError("Failed to get blueprint", ex);
+                try {
+                    json = objectMapper.writeValueAsString(result);
+                } catch (JsonProcessingException jpe) {
+                    // Should never, ever happen
+                    json = "{ \"error\" : \"" + jpe.toString() + "\"}";
+                }
+                return json;
+            } finally {
+                postLogAudit(request);
+            }
+        }
+        try {
+            // process the JSON inputs
+            Map<String, Object> processedInputs = new HashMap<String, Object>();
+            Map<String, Object> mergedInputs = new HashMap<String, Object>();
+            deploymentRequestObject.getInputs()
+            .forEach((k, v) -> translateInputData(processedInputs, k, v));
+            // merge the user inputs with BP input list
+            bpInputDefs = bpItem.getBlueprintInputs();
+            bpInputDefs.forEach((k, v) -> mergeInputData(mergedInputs, processedInputs, k, v));
+            DeploymentResponse resp =
+                deploymentHandlerClient.putDeployment(depName, deploymentRequestObject.getTenant(),
+                    new DeploymentRequest(srvcTypeId, mergedInputs));
+            DeploymentResponseLinks deplLinks = resp.getLinks();
+            String deplStatus = deplLinks.getStatus();
+            if (!deplStatus.contains("cfy_tenant")) {
+                deplStatus = deplStatus + "?cfy_tenant_name=" + deploymentRequestObject.getTenant();
+            }
+            String self = request.getRequestURL().append("/").append(depName).toString();
+            status.append(self).append("/executions?tenant=")
+            .append(deploymentRequestObject.getTenant());
+            DeploymentResource deplRsrc = new DeploymentResource(depName,
+                new DeploymentResourceLinks(self, deplStatus, status.toString()));
+            JSONObject statObj = new JSONObject(deplRsrc);
+            json = statObj.toString();
+            response.setStatus(HttpStatus.SC_ACCEPTED);
+        } catch (BadRequestException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API controller");
+            MDC.put("TargetServiceName", "API controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deployment failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception");
+            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
+        } catch (ServiceAlreadyExistsException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API controller");
+            MDC.put("TargetServiceName", "API controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deployment failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception");
+            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
+        } catch (ServerErrorException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API controller");
+            MDC.put("TargetServiceName", "API controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deployment failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception");
+            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
+        } catch (DownstreamException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API controller");
+            MDC.put("TargetServiceName", "API controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deployment failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception");
+            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
+        } catch (Throwable t) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API controller");
+            MDC.put("TargetServiceName", "API controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deployment failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "createDeployment caught exception");
+            json =
+                objectMapper.writeValueAsString(new RestResponseError("putDeployment failed", t));
+        } finally {
+            postLogAudit(request);
+        }
+        return json;
+    }
+
+    /**
+     * Get the executions for one deployment.
+     * 
+     * 
+     * @param deployment_id Deployment ID (query parameter)
+     * @param request HttpServletRequest
+     * @return CloudifyExecutionList
+     * @throws Exception on serialization failure
+     */
+    @RequestMapping(
+        value = {DEPLOYMENTS_PATH + "/{deploymentId}" + "/" + EXECUTIONS_PATH},
+        method = RequestMethod.GET,
+        produces = "application/json")
+    @ResponseBody
+    public String getExecutionByDeploymentId(@PathVariable("deploymentId") String deploymentId,
+        @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request)
+            throws Exception {
+        preLogAudit(request);
+        ECTransportModel result = null;
+        try {
+            if (tenant == null) {
+                throw new Exception("tenant name is missing");
+            }
+            result = cloudifyClient.getExecutionsSummary(deploymentId, tenant);
+        } catch (HttpStatusCodeException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription",
+                "Getting executions for deployment " + deploymentId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger,
+                "getExecutionByIdAndDeploymentId caught exception");
+            result = new RestResponseError(e.getResponseBodyAsString());
+        } catch (Throwable t) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription",
+                "Getting executions for deployment " + deploymentId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger,
+                "getExecutionByIdAndDeploymentId caught exception");
+            result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t);
+        } finally {
+            postLogAudit(request);
+        }
+        return objectMapper.writeValueAsString(result);
+    }
+
+    /**
+     * Gets the service health for a deployment
+     * 
+     * 
+     * @param deployment_id Deployment ID (query parameter)
+     * @param request HttpServletRequest
+     * @return String
+     * @throws Exception on serialization failure
+     */
+    @RequestMapping(
+        value = {DEPLOYMENTS_PATH + "/{deploymentId}" + "/" + SERVICE_HEALTH_PATH},
+        method = RequestMethod.GET,
+        produces = "application/json")
+    @ResponseBody
+    public String getServiceHealthByDeploymentId(@PathVariable("deploymentId") String deploymentId,
+        HttpServletRequest request) throws Exception {
+        preLogAudit(request);
+        Object result = null;
+        try {
+            result = consulClient.getServiceHealthByDeploymentId(deploymentId);
+        } catch (HttpStatusCodeException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription",
+                "Getting executions for deployment " + deploymentId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger,
+                "getExecutionByIdAndDeploymentId caught exception");
+            result = new RestResponseError(e.getResponseBodyAsString());
+        } catch (Throwable t) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription",
+                "Getting executions for deployment " + deploymentId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger,
+                "getExecutionByIdAndDeploymentId caught exception");
+            result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t);
+        } finally {
+            postLogAudit(request);
+        }
+        return objectMapper.writeValueAsString(result);
+    }
+
+    /**
+     * Query the specified blueprint.
+     *
+     * @param id Blueprint ID
+     * @param request HttpServletRequest
+     * @param response HttpServletResponse
+     * @return status code on success; error on failure.
+     * @throws Exception On serialization failure
+     */
+    @SuppressWarnings("unchecked")
+    @RequestMapping(
+        value = {SERVICE_TYPES_PATH + "/{typeid}"},
+        method = RequestMethod.GET,
+        produces = "application/json")
+    @ResponseBody
+    public String queryBlueprint(@PathVariable("typeid") String typeId, HttpServletRequest request,
+        HttpServletResponse response, ServletUriComponentsBuilder uriBuilder) throws Exception {
+        String json = "";
+        Optional<ServiceType> resultItem = null;
+        try {
+            resultItem = inventoryClient.getServiceType(typeId);
+            if (resultItem.isPresent()) {
+                json = objectMapper.writeValueAsString(resultItem.get());
+            }
+            String uri = request.getRequestURI();
+            if (uri != null && !uri.isEmpty()) {
+            String uri_depl =
+                uriBuilder.replacePath(uri).path("/deployments").build().toUriString();
+            StringBuffer linkHeader = new StringBuffer();
+            String linkStr_depl = "<" + uri_depl + ">; rel=\"" + "deployments" + "\"";
+            linkHeader.append(linkStr_depl);
+            response.addHeader("Link", linkHeader.toString());
+            }
+        } catch (Exception e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Getting page of blueprints items failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getBlueprintsByPage caught exception");
+            RestResponseError result = null;
+            if (e instanceof HttpStatusCodeException)
+                result =
+                new RestResponseError(((HttpStatusCodeException) e).getResponseBodyAsString());
+            else
+                result = new RestResponseError("Failed to get blueprints", e);
+            try {
+                json = objectMapper.writeValueAsString(result);
+            } catch (JsonProcessingException jpe) {
+                // Should never, ever happen
+                json = "{ \"error\" : \"" + jpe.toString() + "\"}";
+            }
+        }
+        return json;
+    }
+
+    /**
+     * Deletes the specified blueprint.
+     *
+     * @param id Blueprint ID
+     * @param request HttpServletRequest
+     * @param response HttpServletResponse
+     * @return status code on success; error on failure.
+     * @throws Exception On serialization failure
+     */
+    @SuppressWarnings("unchecked")
+    @RequestMapping(
+        value = {SERVICE_TYPES_PATH + "/{typeid}"},
+        method = RequestMethod.DELETE,
+        produces = "application/json")
+    @ResponseBody
+    public String deleteBlueprint(@PathVariable("typeid") String typeId, HttpServletRequest request,
+        HttpServletResponse response, ServletUriComponentsBuilder uriBuilder) throws Exception {
+        preLogAudit(request);
+        String json = "{\"204\": \"Blueprint deleted\"}";
+        String bpComp = "";
+        boolean allow = true;
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        lock.readLock().lock();
+        @SuppressWarnings("unchecked")
+        List itemList =
+        (List<ServiceTypeSummary>) getCacheManager().getObject("dcae-service-types");
+        lock.readLock().unlock();
+        try {
+            if (itemList != null) {
+                Predicate<ServiceTypeSummary> idFilter = p -> p.getTypeId().get().equals(typeId);
+
+                itemList = (List<ServiceTypeSummary>) itemList.stream().filter(idFilter)
+                    .collect(Collectors.toList());
+                bpComp = ((ServiceTypeSummary) itemList.get(0)).getComponent();
+            } else {
+                try {
+                    ServiceType item = inventoryClient.getServiceType(typeId).get();
+                    bpComp = ((ServiceType) item).getComponent();
+                } catch (NoSuchElementException nse) {
+                    throw new ServiceTypeNotFoundException("invalid blueprint ID given in query");
+                }
+            }
+            if (!isAuthorized(request, bpComp)) {
+                response.setStatus(HttpStatus.SC_FORBIDDEN);
+                json = objectMapper.writeValueAsString(
+                    new RestResponseError("Un-authorized to perform this operation"));
+                return json;
+            }
+            /*
+            ServiceQueryParams qryParams = new ServiceQueryParams.Builder().typeId(typeId).build();
+            ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams);
+            if (srvcRefs != null && srvcRefs.totalCount > 0) {
+                throw new Exception(
+                    "Services exist for the service type template, delete not permitted");
+            }
+            */
+            
+            // check if these dep_ids exist in cloudify
+            List<CloudifyDeployedTenant> deplForBp = 
+                cloudifyClient.getDeploymentForBlueprint("TID-"+typeId);
+            if (deplForBp.size() > 0 ) {
+                allow = false;
+            } else {                        
+                ServiceQueryParams qryParams = 
+                    new ServiceQueryParams.Builder().typeId(typeId).build();
+                ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams);
+                Set<String> dep_ids = srvcRefs.items.stream().map(x -> ((ServiceRef)x).id).collect(Collectors.toSet());  
+                if (dep_ids.size() > 0) {
+                    // now check again if these dep_ids still exist in cloudify
+                    List<String> allDepNames = cloudifyClient.getDeploymentNamesWithFilter(request);
+                    for (String str: dep_ids) {
+                        if (allDepNames.stream().anyMatch(s->s.equalsIgnoreCase(str))) {
+                            allow = false;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (!allow) {
+                response.setStatus(HttpStatus.SC_BAD_REQUEST);
+                json = objectMapper.writeValueAsString(
+                    new RestResponseError("ERROR: Deployments exist for this blueprint"));
+                /*
+                PrintWriter out = response.getWriter();
+                response.setContentType("application/json");
+                response.setCharacterEncoding("UTF-8");
+                out.print(json);
+                out.flush();
+                */
+                return json;
+            } else {
+                inventoryClient.deleteServiceType(typeId);
+                String uri = request.getRequestURI();
+                if (uri != null && !uri.isEmpty()) {
+                    String uri_str = uri.substring(0, uri.lastIndexOf("/"));
+                    String uri_all = uriBuilder.replacePath(uri_str).build().toUriString();
+                    StringBuffer linkHeader = new StringBuffer();
+                    String linkStr = "<" + uri_all + ">; rel=\"" + "current" + "\"";
+                    linkHeader.append(linkStr);
+                    response.addHeader("Link", linkHeader.toString());
+                }
+            }
+        } catch (ServiceTypeNotFoundException e) {
+            response.setStatus(HttpStatus.SC_GONE);
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception");
+            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
+        } catch (ServiceTypeAlreadyDeactivatedException e) {
+            response.setStatus(HttpStatus.SC_GONE);
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception");
+            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
+        } catch (Throwable t) {
+            response.setStatus(HttpStatus.SC_BAD_GATEWAY);
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception");
+            json =
+                objectMapper.writeValueAsString(new RestResponseError("deleteBlueprint failed", t));
+        } finally {
+            postLogAudit(request);
+        }
+        return json;
+    }
+
+    /**
+     * Un-deploy an application or service
+     * 
+     * @param deploymentId
+     * @param request
+     * @param tenant
+     * @param response
+     * @return
+     * @throws Exception
+     */
+    @SuppressWarnings("unchecked")
+    @RequestMapping(
+        value = {DEPLOYMENTS_PATH + "/{deploymentId}"},
+        method = RequestMethod.DELETE,
+        produces = "application/json")
+    public String deleteDeployment(@PathVariable("deploymentId") String deploymentId,
+        HttpServletRequest request, @RequestParam(value = "tenant", required = true) String tenant,
+        HttpServletResponse response) throws Exception {
+        preLogAudit(request);
+        String json = null;
+        StringBuffer status = new StringBuffer();
+        try {
+            if (tenant == null) {
+                throw new Exception("tenant name is missing");
+            }
+            ReadWriteLock lock = new ReentrantReadWriteLock();
+            lock.readLock().lock();
+            @SuppressWarnings("unchecked")
+            List itemList = (List<CloudifyDeployment>) getCacheManager()
+            .getObject("service-list" + ":" + tenant);
+            lock.readLock().unlock();
+            if (itemList != null) {
+                Predicate<CloudifyDeployment> idFilter = p -> p.id.equals(deploymentId);
+                itemList = (List<CloudifyDeployment>) itemList.stream().filter(idFilter)
+                    .collect(Collectors.toList());
+            } else {
+                CloudifyDeploymentList cfyDeplList =
+                    cloudifyClient.getDeployment(deploymentId, tenant);
+                if (cfyDeplList != null && !cfyDeplList.items.isEmpty()) {
+                    itemList = cfyDeplList.items;
+                }
+            }
+            if (itemList != null && !itemList.isEmpty()) {
+                String depItem = ((CloudifyDeployment) itemList.get(0)).id;
+                if (depItem.contains("_")) {
+                    String depComp = depItem.split("_")[0];
+                    if (!isAuthorized(request, depComp)) {
+                        response.setStatus(HttpStatus.SC_FORBIDDEN);
+                        json = objectMapper.writeValueAsString(
+                            new RestResponseError("Un-authorized to perform this operation"));
+                        return json;
+                    }
+                    deploymentHandlerClient.deleteDeployment(deploymentId, tenant);
+                    String self = request.getRequestURL().toString().split("\\?")[0];
+                    status.append(self).append("/executions?tenant=").append(tenant);
+                    DeploymentResource deplRsrc = new DeploymentResource(deploymentId,
+                        new DeploymentResourceLinks(self, "", status.toString()));
+                    JSONObject statObj = new JSONObject(deplRsrc);
+                    json = statObj.toString();
+                }
+            }
+        } catch (BadRequestException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception");
+            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
+        } catch (ServerErrorException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception");
+            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
+        } catch (DownstreamException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception");
+            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
+        } catch (DeploymentNotFoundException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception");
+            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
+        } catch (Throwable t) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception");
+            json = objectMapper
+                .writeValueAsString(new RestResponseError("deleteDeployment failed", t));
+        } finally {
+            postLogAudit(request);
+        }
+        return json;
+    }
+
+    /**
+     * Cancels an execution.
+     * 
+     * @param id Execution ID
+     * @param deploymentId Deployment ID (not clear why this is needed)
+     * @param action Action to perform (not clear why this is needed)
+     * @param request HttpServletRequest
+     * @param response HttpServletRequest
+     * @return Passes thru HTTP status code from remote endpoint; no body on success
+     * @throws Exception on serialization failure
+     */
+    @RequestMapping(
+        value = {EXECUTIONS_PATH + "/{id}"},
+        method = RequestMethod.POST,
+        produces = "application/json")
+    @ResponseBody
+    public String cancelExecution(@RequestHeader HttpHeaders headers, @PathVariable("id") String id,
+        @RequestBody Map<String, String> parameters, HttpServletRequest request,
+        HttpServletResponse response) throws Exception {
+        preLogAudit(request);
+        ECTransportModel result = null;
+        List<String> tenant = null;
+        try {
+            tenant = headers.get("tenant");
+            result = cloudifyClient.cancelExecution(id, parameters, tenant.get(0));
+        } catch (HttpStatusCodeException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception");
+            result = new RestResponseError(e.getResponseBodyAsString());
+        } catch (Throwable t) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "API Controller");
+            MDC.put("TargetServiceName", "API Controller");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception");
+            result = new RestResponseError("cancelExecution failed on ID " + id, t);
+        } finally {
+            postLogAudit(request);
+        }
+        if (result == null)
+            return null;
+        else
+            return objectMapper.writeValueAsString(result);
+    }
+
+    private void preLogAudit(HttpServletRequest request) {
+        begin = new Date();
+        MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin));
+        MDC.put(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin));
+        MDC.put(SystemProperties.STATUS_CODE, "COMPLETE");
+        String user = null;
+        if (request instanceof CadiWrap) {
+            user = ((CadiWrap) request).getUser();
+        } 
+        logger.setRequestBasedDefaultsIntoGlobalLoggingContext(request, APP_NAME, user, user);
+    }
+
+    private void postLogAudit(HttpServletRequest request) {
+        end = new Date();
+        MDC.put("AlertSeverity", "0");
+        MDC.put("TargetEntity", "API Controller");
+        MDC.put("TargetServiceName", "API Controller");
+        MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(end));
+        MDC.put(SystemProperties.METRICSLOG_END_TIMESTAMP, logDateFormat.format(end));
+        // MDC.put(SystemProperties.MDC_TIMER, Long.toString((end.getTime() - begin.getTime())));
+        logger.info(EELFLoggerDelegate.auditLogger,
+            request.getMethod() + " " + request.getRequestURI());
+        logger.info(EELFLoggerDelegate.metricsLogger,
+            request.getMethod() + " " + request.getRequestURI());
+    }
+}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PaginatedResultsRetrievedEvent.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PaginatedResultsRetrievedEvent.java
new file mode 100644 (file)
index 0000000..051f6e6
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.ccsdk.api.controller;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.context.ApplicationEvent;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+public class PaginatedResultsRetrievedEvent<T> extends ApplicationEvent {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1513813910132068908L;
+    private Class clazz;
+    private ServletUriComponentsBuilder uriBuilder;
+    private HttpServletResponse response;
+    private int page;
+    private int maxPages;
+    private int pageSize;
+    
+    public PaginatedResultsRetrievedEvent(Class clazz,
+            ServletUriComponentsBuilder uriBuilder, HttpServletResponse response,
+            int page, int maxPages, int pageSize) {
+        super(clazz);
+        this.clazz = clazz;
+        this.uriBuilder = uriBuilder;
+        this.response = response;
+        this.page = page;
+        this.maxPages = maxPages;
+        this.pageSize = pageSize;
+    }
+
+    public Class getClazz() {
+        return clazz;
+    }
+
+    public ServletUriComponentsBuilder getUriBuilder() {
+        return uriBuilder;
+    }
+
+    public HttpServletResponse getResponse() {
+        return response;
+    }
+
+    public int getPage() {
+        return page;
+    }
+
+    public int getPageSize() {
+        return pageSize;
+    }
+
+    public int getMaxPages() {
+        return maxPages;
+    }
+
+}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PagingEventListener.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/api/controller/PagingEventListener.java
new file mode 100644 (file)
index 0000000..7b310c6
--- /dev/null
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.ccsdk.api.controller;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+import org.springframework.web.util.UriComponentsBuilder;
+
+@Component
+public class PagingEventListener implements
+        ApplicationListener<PaginatedResultsRetrievedEvent> {
+
+  
+    public static final String REL_COLLECTION = "collection"; 
+    public static final String REL_NEXT = "next"; 
+    public static final String REL_PREV = "prev"; 
+    public static final String REL_FIRST = "first"; 
+    public static final String REL_LAST = "last"; 
+    private static final String PAGE = "page";
+    
+    @Override
+    public void onApplicationEvent(PaginatedResultsRetrievedEvent event) {
+        addLinkHeaderOnPagedResourceRetrieval(event.getUriBuilder(),
+                event.getResponse(), event.getClazz(), event.getPage(),
+                event.getMaxPages(), event.getPageSize());
+    }
+
+    void addLinkHeaderOnPagedResourceRetrieval(ServletUriComponentsBuilder uriBuilder,
+            HttpServletResponse response, Class clazz, int page,
+            int totalPages, int size) {
+       
+        StringBuilder linkHeader = new StringBuilder();
+        if (hasNextPage(page, totalPages)) {
+            String uriNextPage = constructNextPageUri(uriBuilder, page, size);
+            linkHeader.append(createLinkHeader(uriNextPage, "next"));
+        }
+        if (hasPreviousPage(page)) {
+            String uriPrevPage = constructPrevPageUri(uriBuilder, page, size);
+            appendCommaIfNecessary(linkHeader);
+            linkHeader.append(createLinkHeader(uriPrevPage, "prev"));
+        }
+        if (hasFirstPage(page)) {
+            String uriFirstPage = constructFirstPageUri(uriBuilder, size);
+            appendCommaIfNecessary(linkHeader);
+            linkHeader.append(createLinkHeader(uriFirstPage, "first"));
+        }
+        if (hasLastPage(page, totalPages)) {
+            String uriLastPage = constructLastPageUri(uriBuilder, totalPages,
+                    size);
+            appendCommaIfNecessary(linkHeader);
+            linkHeader.append(createLinkHeader(uriLastPage, "last"));
+        }
+        response.addHeader("Link", linkHeader.toString());
+
+    }
+
+    final String constructNextPageUri(final UriComponentsBuilder uriBuilder,
+            final int page, final int size) {
+        return uriBuilder.replaceQueryParam(PAGE, page + 1)
+                .replaceQueryParam("size", size).build().toUriString();
+    }
+
+    final String constructPrevPageUri(final UriComponentsBuilder uriBuilder,
+            final int page, final int size) {
+        return uriBuilder.replaceQueryParam(PAGE, page - 1)
+                .replaceQueryParam("size", size).build().toUriString();
+    }
+
+    final String constructFirstPageUri(final UriComponentsBuilder uriBuilder,
+            final int size) {
+        return uriBuilder.replaceQueryParam(PAGE, 1)
+                .replaceQueryParam("size", size).build().toUriString();
+    }
+
+    final String constructLastPageUri(final UriComponentsBuilder uriBuilder,
+            final int totalPages, final int size) {
+        return uriBuilder.replaceQueryParam(PAGE, totalPages)
+                .replaceQueryParam("size", size).build().toUriString();
+    }
+
+    final boolean hasNextPage(final int page, final int totalPages) {
+        return page < totalPages - 1;
+    }
+
+    final boolean hasPreviousPage(final int page) {
+        return page > 1;
+    }
+
+    final boolean hasFirstPage(final int page) {
+        return hasPreviousPage(page);
+    }
+
+    final boolean hasLastPage(final int page, final int totalPages) {
+        return totalPages > 1 && hasNextPage(page, totalPages);
+    }
+
+    final void appendCommaIfNecessary(final StringBuilder linkHeader) {
+        if (linkHeader.length() > 0) {
+            linkHeader.append(", ");
+        }
+    }
+
+    // template
+
+    protected void plural(final UriComponentsBuilder uriBuilder,
+            final Class clazz) {
+        final String resourceName = clazz.getSimpleName().toString().toLowerCase() + "s";
+                //uriMapper.getUriBase(clazz);
+        uriBuilder.path("/" + resourceName);
+    }
+    
+    public static String createLinkHeader(final String uri, final String rel) { 
+        return "<" + uri + ">; rel=\"" + rel + "\""; 
+    } 
+}
index 93748f3..ae0e849 100644 (file)
@@ -2,7 +2,7 @@
  * =============LICENSE_START=========================================================
  *
  * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 package org.onap.ccsdk.dashboard.controller;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
 
-import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenant;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployment;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyEvent;
-import org.onap.ccsdk.dashboard.model.CloudifyEventList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecution;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList;
-import org.onap.ccsdk.dashboard.model.CloudifyTenant;
 import org.onap.ccsdk.dashboard.model.ECTransportModel;
 import org.onap.ccsdk.dashboard.model.RestResponseError;
 import org.onap.ccsdk.dashboard.model.RestResponsePage;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentExt;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentHelm;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEvent;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPlugin;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenant;
+import org.onap.ccsdk.dashboard.model.cloudify.ServiceRefCfyList;
+import org.onap.ccsdk.dashboard.model.consul.ConsulDeploymentHealth;
+import org.onap.ccsdk.dashboard.model.inventory.Service;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceRef;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeServiceMap;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary;
 import org.onap.ccsdk.dashboard.rest.CloudifyClient;
+import org.onap.ccsdk.dashboard.rest.ConsulClient;
+import org.onap.ccsdk.dashboard.rest.InventoryClient;
 import org.onap.portalsdk.core.domain.User;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.onap.portalsdk.core.objectcache.AbstractCacheManager;
 import org.onap.portalsdk.core.util.SystemProperties;
+import org.onap.portalsdk.core.web.support.AppUtils;
 import org.onap.portalsdk.core.web.support.UserUtils;
 import org.slf4j.MDC;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -66,7 +88,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.client.HttpStatusCodeException;
-
 import com.fasterxml.jackson.core.JsonProcessingException;
 
 /**
@@ -83,12 +104,16 @@ public class CloudifyController extends DashboardRestrictedBaseController {
 
     @Autowired
     CloudifyClient cloudifyClient;
+    @Autowired
+    InventoryClient inventoryClient;
+    @Autowired
+    ConsulClient consulClient;
 
     /**
      * Enum for selecting an item type.
      */
     public enum CloudifyDataItem {
-        BLUEPRINT, DEPLOYMENT, EXECUTION, TENANT;
+        BLUEPRINT, DEPLOYMENT, EXECUTION, TENANT, SERVICE_ID, SERVICE_ID_COUNT;
     }
 
     private static Date begin;
@@ -98,10 +123,24 @@ public class CloudifyController extends DashboardRestrictedBaseController {
     private static final String EXECUTIONS_PATH = "executions";
     private static final String TENANTS_PATH = "tenants";
     private static final String NODE_INSTANCES_PATH = "node-instances";
-    private static final String UPDATE_DEPLOYMENT_PATH = "update-deployment";
     private static final String EVENTS_PATH = "events";
-    private static final String DEP_TENANT_STATUS = "deployment-status";
+    private static final String SERVICE_ID = "service-list";
+    private static final String SERVICE_ID_COUNT = "service-list-count";
+    private static final String PLUGINS_PATH = "plugins";
+    private static final String PLUGIN_COUNT = "plugins-count";
+    private static final String SERVICE_TYPES = "dcae-service-types";
+    
+    private AbstractCacheManager cacheManager;   
+    
+    @Autowired
+    public void setCacheManager(AbstractCacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+    }
 
+    public AbstractCacheManager getCacheManager() {
+        return cacheManager;
+    }
+    
     /**
      * Supports sorting events by timestamp
      */
@@ -122,6 +161,58 @@ public class CloudifyController extends DashboardRestrictedBaseController {
         }
     };
 
+    private void updateBpOwnerId(List<CloudifyDeployment> itemList,
+        Map<String, List<CloudifyDeployedTenant>> ownerDepMap) {
+        for (CloudifyDeployment srvc: (List<CloudifyDeployment>)itemList) {    
+            for (Map.Entry<String, List<CloudifyDeployedTenant>> entry : 
+                ownerDepMap.entrySet()) {
+                List<CloudifyDeployedTenant> deplExtItems = 
+                    entry.getValue().stream().filter((Predicate<? super CloudifyDeployedTenant>) s->s.id.equals(srvc.id)).
+                    collect(Collectors.toList());
+                if (deplExtItems != null && deplExtItems.size() > 0) {
+                    srvc.owner = entry.getKey();
+                    break;
+                }
+            }
+        }
+    }
+    
+    private void updateWorkflowHelmStatus(List<CloudifyDeployment> itemList, 
+        List<CloudifyDeploymentExt> cfyDeplExt,
+        List<CloudifyDeploymentHelm> cfyDeplHelm) {
+        for (CloudifyDeployment srvc: (List<CloudifyDeployment>)itemList) {
+            // correlate the cached data for deployments and deployment extensions
+                List<CloudifyDeploymentExt> deplExtItems = 
+                    cfyDeplExt.stream().filter((Predicate<? super CloudifyDeploymentExt>) s->s.id.equals(srvc.id)).
+                    collect(Collectors.toList());
+                if (deplExtItems != null && deplExtItems.size() > 0) {
+                    srvc.lastExecution = deplExtItems.get(0).lastExecution;
+                }
+        }
+        for (CloudifyDeployment srvc: (List<CloudifyDeployment>)itemList) {
+            // correlate the cached data for deployments and deployment helm info
+                List<CloudifyDeploymentHelm> deplHelmItems = 
+                    cfyDeplHelm.stream().filter((Predicate<? super CloudifyDeploymentHelm>) s->s.id.equals(srvc.id)).
+                    collect(Collectors.toList());
+                if (deplHelmItems != null && deplHelmItems.size() > 0) {
+                    srvc.helmStatus = deplHelmItems.get(0).helmStatus;
+                    srvc.isHelm = deplHelmItems.get(0).isHelm;
+                }
+        }
+    }
+    
+    private void updateHelmInfo(List<CloudifyDeployment> itemList, 
+        List<CloudifyDeploymentExt> cfyDeplExt) {
+        for (CloudifyDeployment srvc: (List<CloudifyDeployment>)itemList) {
+            // correlate the cached data for deployments and deployment extensions
+            List<CloudifyDeploymentExt> deplExtItems = 
+                cfyDeplExt.stream().filter((Predicate<? super CloudifyDeploymentExt>) s->s.id.equals(srvc.id)).
+                collect(Collectors.toList());
+            srvc.helmStatus = deplExtItems.get(0).helmStatus;
+            srvc.isHelm = deplExtItems.get(0).isHelm;
+        }
+    }
+    
     /**
      * Gets one page of objects and supporting information via the REST client. On
      * success, returns a PaginatedRestResponse object as String.
@@ -132,23 +223,300 @@ public class CloudifyController extends DashboardRestrictedBaseController {
      * @return JSON block as String, see above.
      * @throws Exception On any error; e.g., Network failure.
      */
-    @SuppressWarnings({"rawtypes"})
-    private String getItemListForPage(long userId, CloudifyDataItem option, int pageNum,
-        int pageSize) throws Exception {
-        /*
-         * if (this.restClient == null) { this.restClient =
-         * getCloudifyRestClient(userId); }
-         */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    private String getItemListForPage(HttpServletRequest request, long userId, 
+        CloudifyDataItem option, int pageNum, int pageSize, String sortBy, String searchBy) 
+            throws Exception {
+       HttpSession session = AppUtils.getSession(request);
+        String user = UserUtils.getUserSession(request).getLoginId();
+        HashMap<String, Boolean> comp_deploy_tab =
+            (HashMap<String, Boolean>) session.getAttribute("comp_access");
+        String roleLevel = (String) session.getAttribute("role_level");
+        String roleAuth = (String) session.getAttribute("auth_role");
+        if (roleAuth == null) {
+            roleAuth = "READ";
+        }
+        if (roleLevel == null) {
+            roleLevel = "dev";
+        }
+        if (comp_deploy_tab == null) {
+            comp_deploy_tab = new HashMap<String, Boolean>();
+        }
+        Set<String> userApps = (Set<String>) session.getAttribute("authComponents");
+        if (userApps == null) {
+            userApps = new TreeSet<String>();
+        }
         List itemList = null;
+        new ArrayList<Service>();
+        int totalItems = 0;
+        int deplPgSize = 500;
+        int deplPgOffset = 0;
+        String tenantFilterStr = "";
+        String cacheFilterStr = "true";
+        String userFilterStr = "false";
+        String svcRefFilterStr = "";
+        String statusFilterStr = "";
+        String helmFilterStr = "";
+        String ownerFilterStr = "";
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        List<CloudifyDeploymentExt> cfyDeplExt = null;
+        List<CloudifyDeploymentExt> cfyDepExList = new ArrayList<CloudifyDeploymentExt>();
+        List<CloudifyDeploymentHelm> cfyDeplHelm = null;
+        List<CloudifyDeploymentHelm> cfyDeplHelmList = new ArrayList<CloudifyDeploymentHelm>();
+        boolean useCache = true;
+        boolean userLevel = false;
+        List<CloudifyTenant> cfyTenantList = null;
+        // apply tenant search filter
+        if (searchBy != null && !searchBy.isEmpty()) {
+            // parse the search filters string  
+            List<String> searchFilters = 
+                new ArrayList<String>(Arrays.asList(searchBy.split(";")));
+            if (searchFilters.stream().anyMatch(s->s.startsWith("tenant"))) {
+                List<String> tenantsList = searchFilters.stream().filter(s->s.startsWith("tenant")).
+                collect(Collectors.toList());
+                if (tenantsList.get(0).split(":").length > 1) {
+                    tenantFilterStr = tenantsList.get(0).split(":")[1];
+                }
+            }
+            if (searchFilters.stream().anyMatch(s->s.startsWith("cache"))) {
+                List<String> cacheStr = searchFilters.stream().filter(s->s.startsWith("cache")).
+                collect(Collectors.toList());
+                cacheFilterStr = cacheStr.get(0).split(":")[1];
+                useCache = Boolean.parseBoolean(cacheFilterStr);
+            }
+            if (searchFilters.stream().anyMatch(s->s.startsWith("user"))) {
+                List<String> userStr = searchFilters.stream().filter(s->s.startsWith("user")).
+                collect(Collectors.toList());
+                userFilterStr = userStr.get(0).split(":")[1];
+                userLevel = Boolean.parseBoolean(userFilterStr);
+            }
+            if (searchFilters.stream().anyMatch(s->s.startsWith("owner"))) {
+                List<String> ownerList = searchFilters.stream().filter(s->s.startsWith("owner")).
+                    collect(Collectors.toList());
+                ownerFilterStr = ownerList.get(0).split(":")[1];
+            }
+        }
+        lock.readLock().lock();
+        Map<String, List<CloudifyDeployedTenant>> deplPerOwner = 
+            (Map<String, List<CloudifyDeployedTenant>>) getCacheManager().getObject("owner_deploy_map");
+        lock.readLock().unlock();
         switch (option) {
-            /*
-             * case BLUEPRINT: itemList = restClient.getBlueprints().items;
-             * Collections.sort(itemList, blueprintComparator); break; case DEPLOYMENT:
-             * itemList = restClient.getDeployments().items; Collections.sort(itemList,
-             * deploymentComparator); break;
-             */
+            case SERVICE_ID_COUNT:
+                List items = null;
+                if (!ownerFilterStr.isEmpty()) {
+                    if (deplPerOwner != null) {
+                        List<CloudifyDeployedTenant> ownerDeplList = deplPerOwner.get(user); 
+                        items = ownerDeplList;
+                    }
+                } else {
+                    List<CloudifyDeployment> itemsList = 
+                        cloudifyClient.getDeploymentsWithFilter(request);
+                    items = itemsList;
+                }
+                if (items == null) {
+                    items = new ArrayList<CloudifyDeployment>();
+                }
+                totalItems = items.size();
+                RestResponsePage<List> model = 
+                    new RestResponsePage<>(totalItems, 1, items);
+                String outboundJson = objectMapper.writeValueAsString(model);
+                return outboundJson;
+            case SERVICE_ID: 
+                final String svcIdTenant = tenantFilterStr;
+                if (useCache) {
+                    lock.readLock().lock();
+                    itemList = 
+                        (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + svcIdTenant);
+                    lock.readLock().unlock();
+                }
+                if (itemList == null) {
+                    itemList = cloudifyClient.getDeployments(tenantFilterStr, deplPgSize, deplPgOffset, true);
+                }
+                Set<String> svcIdList = new HashSet<String>();
+                if (itemList != null) {
+                    svcIdList = 
+                    (Set) itemList.stream().map(x -> ((CloudifyDeployment)x).id).collect(Collectors.toSet());
+                    // apply role based filtering
+                    if (roleLevel.equals("app")) {
+                        @SuppressWarnings("unchecked")
+                        List<String> myApps = new ArrayList(userApps);
+                        svcIdList = svcIdList.stream().filter(s -> myApps.stream()
+                            .anyMatch(roleFilter -> ((String)s).toLowerCase().startsWith(roleFilter)))
+                            .collect(Collectors.toSet());         
+                    } 
+                }
+                return objectMapper.writeValueAsString(svcIdList);
+            case DEPLOYMENT:
+                itemList = new ArrayList<CloudifyDeployment>();
+                List<CloudifyDeployment> cfyDepPerTntList = null;
+                List<CloudifyDeployment> cfyDepList = null;
+                try {
+                    if (tenantFilterStr.isEmpty()) {
+                        cfyDepList = new ArrayList<CloudifyDeployment>();
+                        if (useCache) {
+                            lock.readLock().lock();
+                            cfyTenantList = (List<CloudifyTenant>)getCacheManager().getObject(TENANTS_PATH);
+                            for (CloudifyTenant cfyTenObj: cfyTenantList) {
+                                cfyDepPerTntList = (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + cfyTenObj.name);
+                                cfyDepList.addAll(cfyDepPerTntList);
+                            }
+                            lock.readLock().unlock();
+                        } else {
+                            cfyTenantList = (List<CloudifyTenant>)cloudifyClient.getTenants().items;
+                            for (CloudifyTenant cfyTenObj: cfyTenantList) {
+                                cfyDepPerTntList = cloudifyClient.getDeployments(cfyTenObj.name, deplPgSize, deplPgOffset, true, false);
+                                cfyDepList.addAll(cfyDepPerTntList);
+                            }
+                        } 
+                    } else {
+                        if (useCache) {
+                            lock.readLock().lock();
+                            cfyDepList = (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + tenantFilterStr);
+                            lock.readLock().unlock();
+                        }
+                        if (cfyDepList == null) {
+                            cfyDepList = cloudifyClient.getDeployments(tenantFilterStr, deplPgSize, deplPgOffset, true, false);                         
+                        }
+                    }
+                    totalItems = cfyDepList.size();
+                    
+                    if (useCache) {
+                        lock.readLock().lock();
+                        cfyDeplExt = 
+                            (List<CloudifyDeploymentExt>)getCacheManager().getObject(SERVICE_ID + ":" + tenantFilterStr + ":ext");
+                        if (cfyDeplExt != null) {
+                            cfyDepExList.addAll(cfyDeplExt);
+                        }
+                        cfyDeplHelm = 
+                            (List<CloudifyDeploymentHelm>)getCacheManager().getObject(SERVICE_ID + ":" + tenantFilterStr + ":helm");
+                        if (cfyDeplHelm != null) {
+                            cfyDeplHelmList.addAll(cfyDeplHelm);
+                        }
+                        lock.readLock().unlock();                    
+                    }
+                    
+                    if (roleLevel.equals("app") && !userLevel) {
+                        @SuppressWarnings("unchecked")
+                        List<String> myApps = new ArrayList(userApps);
+                        cfyDepList = (List) cfyDepList.stream().filter(s -> myApps.stream()
+                            .anyMatch(roleFilter -> ((CloudifyDeployment)s).id.toLowerCase().startsWith(roleFilter)))
+                            .collect(Collectors.toList());         
+                    }                 
+                    // apply user search filters
+                    if (searchBy != null && !searchBy.isEmpty()) {
+                        // parse the search filters string 
+                        // look for service name patterns                  
+                        List<String> searchFilters = 
+                            new ArrayList<String>(Arrays.asList(searchBy.split(";")));
+                        if (searchFilters.stream().anyMatch(s->s.startsWith("serviceRef"))) {
+                            List<String> svcRefsList = searchFilters.stream().filter(s->s.startsWith("serviceRef")).
+                            collect(Collectors.toList());
+                            svcRefFilterStr = svcRefsList.get(0).split(":")[1];
+                        }
+                        if (searchFilters.stream().anyMatch(s->s.startsWith("status"))) {
+                            List<String> statusList = searchFilters.stream().filter(s->s.startsWith("status")).
+                            collect(Collectors.toList());
+                            statusFilterStr = statusList.get(0).split(":")[1];
+                        }
+                        if (searchFilters.stream().anyMatch(s->s.startsWith("helm"))) {
+                            List<String> helmList = searchFilters.stream().filter(s->s.startsWith("helm")).
+                            collect(Collectors.toList());
+                            helmFilterStr = helmList.get(0).split(":")[1];
+                        }          
+                        if (!ownerFilterStr.isEmpty()) {
+                            List ownerFilterList = 
+                                    new ArrayList<String>(Arrays.asList(ownerFilterStr.split(",")));                
+                            if (ownerFilterList.size() == 1 && ownerFilterList.get(0).equals("undefined")) {
+                                ownerFilterList.clear();
+                                ownerFilterList.add(user);
+                            }
+                            if (deplPerOwner != null && cfyDepList != null) {
+                                List<CloudifyDeployedTenant> ownerDeplList = new ArrayList<CloudifyDeployedTenant>();
+                                Stream<Map.Entry<String, List<CloudifyDeployedTenant>>> deplOwnerEntriesStream = 
+                                    deplPerOwner.entrySet().stream(); 
+                                Set<Map.Entry<String, List<CloudifyDeployedTenant>>> deplOwnerSet = 
+                                    deplOwnerEntriesStream.filter(m -> ownerFilterList.stream().
+                                    anyMatch(ownFilter -> m.getKey().equalsIgnoreCase((String) ownFilter))).collect(Collectors.toSet());
+                                deplOwnerSet.stream().forEach(e -> ownerDeplList.addAll(e.getValue()));
+                                if (ownerDeplList.size() > 0) {
+                                    Predicate<CloudifyDeployment> In2 = 
+                                        s -> ownerDeplList.stream().anyMatch(mc -> s.id.equals(mc.id));
+                                    cfyDepList = cfyDepList.stream().filter(In2).collect(Collectors.toList());
+                                } else {
+                                    cfyDepList = new ArrayList<CloudifyDeployment>();
+                                }
+                            }
+                        }
+                        if (!svcRefFilterStr.isEmpty()) {
+                            List<String> svcFilterList = 
+                                new ArrayList<String>(Arrays.asList(svcRefFilterStr.split(",")));
+                            if (!svcFilterList.isEmpty()) {
+                                cfyDepList =  (List) cfyDepList.stream().filter(s -> svcFilterList.stream()
+                                    .anyMatch(svcFilter -> ((CloudifyDeployment) s).id.toLowerCase().contains(svcFilter.toLowerCase())))
+                                    .collect(Collectors.toList());
+                            }
+                        }
+                        if (!statusFilterStr.isEmpty()) {
+                            List<String> statusFilterList = 
+                                new ArrayList<String>(Arrays.asList(statusFilterStr.split(",")));                       
+                            Predicate<CloudifyDeployment> srvcFilter =
+                                p -> p.lastExecution.status != null;
+                            Stream<CloudifyDeployment> svcStream = cfyDepList.stream(); 
+                            if (cfyDepExList == null || cfyDepExList.isEmpty()) {
+                                cfyDepExList = cloudifyClient.updateWorkflowStatus(cfyDepList);
+                            }
+                            if (cfyDepExList != null) {
+                                updateWorkflowHelmStatus(cfyDepList, cfyDepExList, cfyDeplHelmList);
+                                cfyDepList =  svcStream.filter( srvcFilter.and(
+                                    s -> statusFilterList.stream()
+                                    .anyMatch(statusFilter ->((CloudifyDeployment) s).lastExecution.status.equalsIgnoreCase(statusFilter))))
+                                    .collect(Collectors.toList()); 
+                            }
+                        }                      
+                        if (!helmFilterStr.isEmpty()) {
+                            Predicate<CloudifyDeployment> helmFilter =
+                                p -> p.helmStatus != null;
+                            boolean isHelm = Boolean.parseBoolean(helmFilterStr);
+                            if (cfyDeplHelmList == null || cfyDeplHelmList.isEmpty()) {
+                                cfyDeplHelmList = cloudifyClient.updateHelmInfo(cfyDepList);
+                            }
+                            if (cfyDeplHelmList != null && isHelm ) {
+                                updateWorkflowHelmStatus(cfyDepList, cfyDepExList, cfyDeplHelmList);
+                                cfyDepList =  (List) cfyDepList.stream().filter(helmFilter.and(
+                                    s -> ((CloudifyDeployment) s).isHelm == true))
+                                .collect(Collectors.toList()); 
+                            }
+                        } 
+                    } 
+                    itemList.addAll(cfyDepList);
+                } catch (Exception cfyDepErr) {
+                    logger.error(EELFLoggerDelegate.errorLogger, cfyDepErr.getMessage());
+                }
+                if (sortBy != null) {
+                    if (sortBy.equals("id")) {
+                        ((List<CloudifyDeployment>)itemList).sort(
+                            (CloudifyDeployment o1, CloudifyDeployment o2) -> o1.id.compareTo(o2.id));
+                    } else if (sortBy.equals("blueprint_id")) {
+                        ((List<CloudifyDeployment>)itemList).sort(
+                            (CloudifyDeployment o1, CloudifyDeployment o2) -> o1.blueprint_id.compareTo(o2.blueprint_id));
+                    } else if (sortBy.equals("created_at")) {
+                        ((List<CloudifyDeployment>)itemList).sort(
+                            (CloudifyDeployment o1, CloudifyDeployment o2) -> o1.created_at.compareTo(o2.created_at));
+                    } else if (sortBy.equals("updated_at")) {
+                        ((List<CloudifyDeployment>)itemList).sort(
+                            (CloudifyDeployment o1, CloudifyDeployment o2) -> o1.updated_at.compareTo(o2.updated_at));
+                    }
+                }
+                break;          
             case TENANT:
-                itemList = cloudifyClient.getTenants().items;
+                lock.readLock().lock();
+                cfyTenantList = (List<CloudifyTenant>)getCacheManager().getObject(TENANTS_PATH);
+                lock.readLock().unlock();
+                if (cfyTenantList == null || cfyTenantList.isEmpty()) {
+                    cfyTenantList = (List<CloudifyTenant>)cloudifyClient.getTenants().items;
+                }
+                
+                itemList = cfyTenantList;
                 break;
             default:
                 MDC.put(SystemProperties.STATUS_CODE, "ERROR");
@@ -162,10 +530,78 @@ public class CloudifyController extends DashboardRestrictedBaseController {
                     "getItemListForPage failed: unimplemented case: " + option.name());
         }
         // Shrink if needed
-        final int totalItems = itemList.size();
+        if (itemList != null) {
+            totalItems = itemList.size();
+        }
         final int pageCount = (int) Math.ceil((double) totalItems / pageSize);
-        if (totalItems > pageSize)
+        if (totalItems > pageSize) {
             itemList = getPageOfList(pageNum, pageSize, itemList);
+        }
+
+        if (option.equals(CloudifyDataItem.DEPLOYMENT)) {
+            // update blueprint owner for each deployment record
+            if (deplPerOwner != null ) {
+                updateBpOwnerId(itemList, deplPerOwner);
+            }
+            if (cfyDepExList == null || cfyDepExList.isEmpty()) {
+                cfyDepExList = cloudifyClient.updateWorkflowStatus(itemList);
+            }
+            if (cfyDeplHelmList == null || cfyDeplHelmList.isEmpty()) {
+                cfyDeplHelmList = cloudifyClient.updateHelmInfo(itemList);
+            }
+            for (CloudifyDeployment srvc: (List<CloudifyDeployment>)itemList) {
+                try {
+                    ConsulDeploymentHealth serviceHealth = 
+                        consulClient.getServiceHealthByDeploymentId(srvc.id);
+                    if (serviceHealth != null) {
+                        srvc.healthStatus = serviceHealth.getStatus();
+                    }
+                } catch (Exception e) {
+                    logger.error(EELFLoggerDelegate.errorLogger, "consul getServiceHealth caught exception");
+                }
+                // correlate the cached data for deployments and deployment extensions               
+                if (cfyDepExList != null) {
+                    List<CloudifyDeploymentExt> deplExtItems = 
+                        cfyDepExList.stream().filter((Predicate<? super CloudifyDeploymentExt>) s->s.id.equals(srvc.id)).
+                        collect(Collectors.toList());
+                    if (deplExtItems != null && !deplExtItems.isEmpty()) {
+                        srvc.lastExecution = deplExtItems.get(0).lastExecution;
+                    }
+                }
+                if (cfyDeplHelmList != null) {
+                    List<CloudifyDeploymentHelm> deplHelmItems = 
+                        cfyDeplHelmList.stream().filter((Predicate<? super CloudifyDeploymentHelm>) s->s.id.equals(srvc.id)).
+                        collect(Collectors.toList());
+                    if (deplHelmItems != null && !deplHelmItems.isEmpty()) {
+                        srvc.helmStatus = deplHelmItems.get(0).helmStatus;
+                        srvc.isHelm = deplHelmItems.get(0).isHelm;
+                    }
+                }
+            }
+            // check for authorization to perform delete deployed blueprints
+            if (!roleLevel.equals("ops")) {
+                if (roleLevel.equals("dev") || roleLevel.equals("app_dev")) {
+                    boolean deployFlag = roleAuth.equals("WRITE") ? true : false;
+                    for (CloudifyDeployment srvc : (List<CloudifyDeployment>) itemList) {
+                        srvc.canDeploy = deployFlag;
+                    }
+                } else {
+                    for (CloudifyDeployment srvc : (List<CloudifyDeployment>) itemList) {
+                        String deplRef = srvc.id.split("_")[0].toLowerCase();
+                        if (comp_deploy_tab.containsKey(deplRef)) {
+                            boolean enableDeploy = comp_deploy_tab.get(deplRef);
+                            srvc.canDeploy = enableDeploy;
+                        } else {
+                            srvc.canDeploy = false;
+                        }
+                    }
+                }
+            } else {
+                for (CloudifyDeployment srvc : (List<CloudifyDeployment>) itemList) {
+                    srvc.canDeploy = true;
+                }
+            }
+        }           
         RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList);
         String outboundJson = objectMapper.writeValueAsString(model);
         return outboundJson;
@@ -177,9 +613,12 @@ public class CloudifyController extends DashboardRestrictedBaseController {
      * 
      * @param request Inbound request
      * @param option  Item type to get
+     * @param inputKey Input key to search for if using filters
+     * @param inputValue Input value to search for if using filters
      * @return JSON with one page of objects; or an error.
      */
-    protected String getItemListForPageWrapper(HttpServletRequest request, CloudifyDataItem option) {
+    protected String getItemListForPageWrapper(HttpServletRequest request, CloudifyDataItem option,
+        String sortBy, String searchBy) {
         String outboundJson = null;
         try {
             User appUser = UserUtils.getUserSession(request);
@@ -187,7 +626,8 @@ public class CloudifyController extends DashboardRestrictedBaseController {
                 throw new Exception("getItemListForPageWrapper: Failed to get application user");
             int pageNum = getRequestPageNumber(request);
             int pageSize = getRequestPageSize(request);
-            outboundJson = getItemListForPage(appUser.getId(), option, pageNum, pageSize);
+            outboundJson = getItemListForPage(request, appUser.getId(), option, pageNum, pageSize,
+                sortBy, searchBy);
         } catch (Exception ex) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "Cloudify Manager");
@@ -210,7 +650,162 @@ public class CloudifyController extends DashboardRestrictedBaseController {
         }
         return outboundJson;
     }
+    
 
+    /**
+     * Serves one page of deployments
+     * 
+     * @param request HttpServletRequest
+     * @return List of CloudifyDeployment objects
+     */
+      @RequestMapping(value = { DEPLOYMENTS_PATH }, method = RequestMethod.GET,
+      produces = "application/json")     
+      @ResponseBody 
+      public String getDeploymentsByPage(HttpServletRequest request)
+      { 
+          preLogAudit(request); 
+          String json = getItemListForPageWrapper(request,
+          CloudifyDataItem.DEPLOYMENT,request.getParameter("sortBy"), request.getParameter("searchBy")); 
+          postLogAudit(request); 
+          return json; 
+      }
+     
+      /**
+       * Gets the specified blueprint content for viewing.
+       * 
+       * @param id
+       *            Blueprint ID
+       * @param request
+       *            HttpServletRequest
+       * @return Blueprint as YAML; or error.
+       * @throws Exception
+       *             on serialization error
+       * 
+       */
+      @RequestMapping(value = {
+              BLUEPRINTS_PATH + "/{id:.+}" + "/archive" }, method = RequestMethod.GET, produces = "application/yaml")
+      @ResponseBody
+      public byte[] viewBlueprintContentById(@PathVariable("id") String id, @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request) throws Exception {
+          preLogAudit(request);
+          byte[] result = null;
+          try {
+              result = cloudifyClient.viewBlueprint(tenant, id);
+          } catch (HttpStatusCodeException e) {
+              MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+              MDC.put("TargetEntity", "Cloudify Manager");
+              MDC.put("TargetServiceName", "Cloudify Manager");
+              MDC.put("ErrorCode", "300");
+              MDC.put("ErrorCategory", "ERROR");
+              MDC.put("ErrorDescription", "Viewing blueprint " + id + " failed!");
+              logger.error(EELFLoggerDelegate.errorLogger, "viewBlueprintContentById caught exception");
+              //result = new RestResponseError(e.getResponseBodyAsString());
+          } catch (Throwable t) {
+              MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+              MDC.put("TargetEntity", "Cloudify Manager");
+              MDC.put("TargetServiceName", "Cloudify Manager");
+              MDC.put("ErrorCode", "300");
+              MDC.put("ErrorCategory", "ERROR");
+              MDC.put("ErrorDescription", "Viewing blueprint " + id + " failed!");
+              logger.error(EELFLoggerDelegate.errorLogger, "viewBlueprintContentById caught exception");
+              //result = new RestResponseError("getBlueprintContentById failed", t);
+          } finally {
+              postLogAudit(request);
+          }
+          return result;
+              //objectMapper.writeValueAsString(result);
+      }
+
+      /**
+       * Serves the complete list of deployment IDs
+       * 
+       * @param request HttpServletRequest
+       * 
+       * @return list of cloudify deployment IDs
+       */
+      @RequestMapping(
+          value = {SERVICE_ID},
+          method = RequestMethod.GET,
+          produces = "application/json")
+      @ResponseBody
+      public String getAllServiceNames(HttpServletRequest request) {
+          preLogAudit(request);
+          String json = null;
+          json = getItemListForPageWrapper(request, CloudifyDataItem.SERVICE_ID,
+              request.getParameter("sortBy"), request.getParameter("searchBy"));
+          postLogAudit(request);
+          return json;
+      }  
+      
+      /**
+       * Serves the count of deployment IDs
+       * 
+       * @param request HttpServletRequest
+       * 
+       * @return list of cloudify deployment IDs
+       */
+      @RequestMapping(
+          value = {SERVICE_ID_COUNT},
+          method = RequestMethod.GET,
+          produces = "application/json")
+      @ResponseBody
+      public String getDepCount(HttpServletRequest request) {
+          preLogAudit(request);
+          String json = null;
+          json = getItemListForPageWrapper(request, CloudifyDataItem.SERVICE_ID_COUNT,
+              request.getParameter("sortBy"), request.getParameter("searchBy"));
+          postLogAudit(request);
+          return json;
+      } 
+      
+      /**
+       * Serves the count of plugins
+       * 
+       * @param request HttpServletRequest
+       * 
+       * @return count of cloudify plugins
+     * @throws JsonProcessingException 
+       */
+      @RequestMapping(
+          value = {PLUGIN_COUNT},
+          method = RequestMethod.GET,
+          produces = "application/json")
+      @ResponseBody
+      public String getPluginCount(HttpServletRequest request) 
+          throws JsonProcessingException {
+          preLogAudit(request);
+          ECTransportModel result = null;        
+          try {
+              int totalItems = 
+                  (int) cloudifyClient.getPlugins().metadata.pagination.total;              
+              RestResponsePage<List> model = 
+                  new RestResponsePage<>(totalItems, 1, null);
+              String outboundJson = objectMapper.writeValueAsString(model);
+              return outboundJson;
+          } catch (HttpStatusCodeException e) {
+              MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+              MDC.put("TargetEntity", "Cloudify Manager");
+              MDC.put("TargetServiceName", "Cloudify Manager");
+              MDC.put("ErrorCode", "300");
+              MDC.put("ErrorCategory", "ERROR");
+              MDC.put("ErrorDescription", "Getting plugins failed!");
+              logger.error(EELFLoggerDelegate.errorLogger, "getPlugins caught exception");
+              result = new RestResponseError(e.getResponseBodyAsString());
+              return objectMapper.writeValueAsString(result);
+          } catch (Throwable t) {
+              MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+              MDC.put("TargetEntity", "Cloudify Manager");
+              MDC.put("TargetServiceName", "Cloudify Manager");
+              MDC.put("ErrorCode", "300");
+              MDC.put("ErrorCategory", "ERROR");
+              MDC.put("ErrorDescription", "Getting plugins failed!");
+              logger.error(EELFLoggerDelegate.errorLogger, "getPlugins caught exception");
+              result = new RestResponseError("getSecret failed", t);
+              return objectMapper.writeValueAsString(result);
+          } finally {
+              postLogAudit(request);
+          }
+      } 
+      
     /**
      * gets the tenants list
      * 
@@ -221,11 +816,12 @@ public class CloudifyController extends DashboardRestrictedBaseController {
     @ResponseBody
     public String getTenants(HttpServletRequest request) {
         preLogAudit(request);
-        String json = getItemListForPageWrapper(request, CloudifyDataItem.TENANT);
+        String json = getItemListForPageWrapper(request, CloudifyDataItem.TENANT,
+            request.getParameter("sortBy"), request.getParameter("searchBy"));
         postLogAudit(request);
         return json;
     }
-
+   
     /**
      * Gets the specified blueprint metadata.
      * 
@@ -235,7 +831,7 @@ public class CloudifyController extends DashboardRestrictedBaseController {
      * @throws Exception on serialization error
      * 
      */
-    @RequestMapping(value = { BLUEPRINTS_PATH + "/{id}" }, method = RequestMethod.GET, produces = "application/json")
+    @RequestMapping(value = { BLUEPRINTS_PATH + "/{id:.+}" }, method = RequestMethod.GET, produces = "application/json")
     @ResponseBody
     public String getBlueprintById(@PathVariable("id") String id,
             @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request)
@@ -269,161 +865,208 @@ public class CloudifyController extends DashboardRestrictedBaseController {
     }
 
     /**
-     * Gets the specified deployment.
+     * Deletes the specified blueprint.
      * 
-     * @param id      Deployment ID
-     * @param request HttpServletRequest
-     * @return Deployment for the specified ID; error on failure.
+     * @param id       Blueprint ID
+     * @param request  HttpServletRequest
+     * @param response HttpServletResponse
+     * @return No content on success; error on failure.
      * @throws Exception On serialization failure
-     * 
      */
-    @RequestMapping(value = { DEPLOYMENTS_PATH + "/{id}" }, method = RequestMethod.GET, produces = "application/json")
-    @ResponseBody
-    public String getDeploymentById(@PathVariable("id") String id,
-            @RequestParam(value = "tenant", required = false) String tenant, HttpServletRequest request)
-            throws Exception {
+      @RequestMapping(value = { BLUEPRINTS_PATH + "/{id}" }, method = RequestMethod.DELETE, produces = "application/json")   
+      @ResponseBody 
+      public String deleteBlueprint(@PathVariable("id") String id,
+          @RequestParam(value = "tenant", required = false) String tenant, 
+        HttpServletRequest request, HttpServletResponse response) throws Exception {
         preLogAudit(request);
-        ECTransportModel result = null;
+        String json = "{\"202\": \"OK\"}";
         try {
-            if (tenant != null && tenant.length() > 0) {
-                result = cloudifyClient.getDeployment(id, tenant);
-            } else {
-                result = cloudifyClient.getDeployment(id);
-            }
+            cloudifyClient.deleteBlueprint(id, tenant);
+            response.setStatus(202);
         } catch (HttpStatusCodeException e) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "Cloudify Manager");
             MDC.put("TargetServiceName", "Cloudify Manager");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting deployment " + id + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getDeploymentById caught exception");
-            result = new RestResponseError(e.getResponseBodyAsString());
-        } catch (Exception t) {
+            MDC.put("ErrorDescription", "Deleting blueprint " + id + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception");
+            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
+        } catch (Throwable t) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "Cloudify Manager");
             MDC.put("TargetServiceName", "Cloudify Manager");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting deployment " + id + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getDeploymentById caught exception");
-            result = new RestResponseError("getDeploymentById failed", t);
+            MDC.put("ErrorDescription", "Deleting blueprint " + id + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception");
+            json = objectMapper
+                .writeValueAsString(new RestResponseError("deleteBlueprint failed on ID " + id, t));
         } finally {
             postLogAudit(request);
         }
-        return objectMapper.writeValueAsString(result);
+        return json;
     }
+     
+    /**
+     * 
+     * Deployment IDs for the given list of blueprint IDs
+     * 
+     */
+      @RequestMapping(
+          value = {"deployment_blueprint_map"},
+          method = RequestMethod.POST,
+          produces = "application/json")
+      @ResponseBody
+      public String getDeploymentsForType(HttpServletRequest request, @RequestBody String[] typeList)
+          throws Exception {
+          List<ServiceTypeServiceMap> result = new ArrayList<ServiceTypeServiceMap>();
+          for (String typeId : typeList) { 
+              List<CloudifyDeployedTenant> deplForBpAggr = new ArrayList<CloudifyDeployedTenant>();             
+              List<CloudifyDeployedTenant> deplForBp = 
+                  cloudifyClient.getDeploymentForBlueprint("TID-"+typeId);
+              deplForBpAggr.addAll(deplForBp);
+              
+              ServiceQueryParams qryParams = 
+                  new ServiceQueryParams.Builder().typeId(typeId).build();
+              ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams);            
+              Set<String> dep_ids = srvcRefs.items.stream().map(x -> ((ServiceRef)x).id).collect(Collectors.toSet());  
+              if (dep_ids.size() > 0) {
+                  // lookup these dep_ids in cloudify for tenant mapping                 
+                  for (String str: dep_ids) {
+                      List<CloudifyDeployedTenant> deplForBpInv = 
+                          cloudifyClient.getDeploymentForBlueprint(str);
+                      deplForBpAggr.addAll(deplForBpInv);
+                  }
+              } 
+              ServiceRefCfyList cfyDeplRefList = new ServiceRefCfyList(deplForBpAggr, deplForBpAggr.size());
+              ServiceTypeServiceMap srvcMap = new ServiceTypeServiceMap(typeId, cfyDeplRefList);
+              result.add(srvcMap);
+          }
+          String resultStr = objectMapper.writeValueAsString(result);
+          return resultStr;
+      }
+
+      @SuppressWarnings("unchecked")
+      @Scheduled(fixedDelay=3600000, initialDelay=180000)
+      public void cacheOwnerDeployMap() {
+          logger.debug(EELFLoggerDelegate.debugLogger, "cacheOwnerDeployMap begin");
+          Map<String, List<CloudifyDeployedTenant>> deplPerOwner = 
+              new HashMap<String, List<CloudifyDeployedTenant>>();
+          new HashMap<String, List<ServiceTypeSummary>>();
+          List<ServiceTypeSummary> bpNoDeplItems = 
+              new ArrayList<ServiceTypeSummary>();
+          List<ServiceTypeServiceMap> result = new ArrayList<ServiceTypeServiceMap>();
+          List<CloudifyDeployedTenant> deplForBpAggr = 
+              new ArrayList<CloudifyDeployedTenant>();
+          String typeId = "";
+          String owner = "";
+          
+          ReadWriteLock lock = new ReentrantReadWriteLock();
+          lock.readLock().lock();
+          List<ServiceTypeSummary> bpItems = 
+              (List<ServiceTypeSummary>) getCacheManager().getObject(SERVICE_TYPES);
+          lock.readLock().unlock();
+          if (bpItems != null) {
+              for (ServiceTypeSummary item : bpItems) {
+                  try {
+                      typeId = item.getTypeId().get();
+                      owner = item.getOwner();                     
+                      List<CloudifyDeployedTenant> deplForBp = 
+                          cloudifyClient.getDeploymentForBlueprint("TID-"+typeId);
+                      deplForBpAggr.clear();
+                      deplForBpAggr.addAll(deplForBp);
+                      ServiceQueryParams qryParams = 
+                          new ServiceQueryParams.Builder().typeId(typeId).build();
+                      ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams);            
+                      Set<String> dep_ids = srvcRefs.items.stream().map(x -> ((ServiceRef)x).id).collect(Collectors.toSet());  
+                      if (dep_ids.size() > 0) {                
+                          for (String str: dep_ids) {
+                              List<CloudifyDeployedTenant> deplForBpInv = 
+                                  cloudifyClient.getDeploymentForBlueprint(str);
+                              deplForBpAggr.addAll(deplForBpInv);
+                          }
+                      }                  
+                  } catch (Exception e) {
+                      logger.error(EELFLoggerDelegate.errorLogger, "cacheOwnerDeployMap: " + e.getMessage());
+                  } finally {
+                      if (deplForBpAggr.isEmpty()) {
+                          bpNoDeplItems.add(item);
+                      }
+                      List<CloudifyDeployedTenant> iterBpIdDepl = 
+                          new ArrayList<CloudifyDeployedTenant>();
+                      iterBpIdDepl.addAll(deplForBpAggr);
+                      ServiceRefCfyList cfyDeplRefList = new ServiceRefCfyList(iterBpIdDepl, iterBpIdDepl.size());
+                      ServiceTypeServiceMap srvcMap = new ServiceTypeServiceMap(typeId, cfyDeplRefList);
+                      result.add(srvcMap); 
+                      
+                      List<CloudifyDeployedTenant> iterDeplBpAggr = 
+                          new ArrayList<CloudifyDeployedTenant>();
+                      iterDeplBpAggr.addAll(deplForBpAggr);
+                      if (deplPerOwner.containsKey(owner)) {
+                          List<CloudifyDeployedTenant> currOwnerDepl = 
+                              deplPerOwner.get(owner);
+                          iterDeplBpAggr.addAll(0, currOwnerDepl);
+                          deplPerOwner.put(owner, iterDeplBpAggr);
+                      }  else {
+                          deplPerOwner.putIfAbsent(owner, iterDeplBpAggr);
+                      }  
+                  }
+              }
+          }
 
+          lock.writeLock().lock();
+          getCacheManager().putObject("bp_deploy_map", result);
+          getCacheManager().putObject("owner_deploy_map", deplPerOwner);
+          lock.writeLock().unlock();
+      }
+      
     /**
-     * Query status and tenant info for deployments
+     * Gets the specified deployment.
+     * 
+     * @param id      Deployment ID
+     * @param request HttpServletRequest
+     * @return Deployment for the specified ID; error on failure.
+     * @throws Exception On serialization failure
      * 
      */
-    @SuppressWarnings("unchecked")
-    @RequestMapping(value = { DEP_TENANT_STATUS }, method = RequestMethod.POST, produces = "application/json")
+    @RequestMapping(value = { DEPLOYMENTS_PATH + "/{id:.+}" }, method = RequestMethod.GET, produces = "application/json")
     @ResponseBody
-    public String getTenantStatusForService(HttpServletRequest request, @RequestBody String[] serviceList)
+    public String getDeploymentById(@PathVariable("id") String id,
+            @RequestParam(value = "tenant", required = false) String tenant, HttpServletRequest request)
             throws Exception {
         preLogAudit(request);
-        /*
-         * 1) Get all the tenant names 2) Get the deployment IDs per tenant for all the
-         * tenants, aggregate the deployments list 3) Get the input deployments list
-         * (screen input), filter the deployments list from step#2 4) For each item in
-         * the list from step#3, get the execution status info and generate the final
-         * response
-         */
-        String outboundJson = "";
-        CloudifyDeployedTenantList cfyTenantDeployMapList = null;
-        new HashMap<String, Object>();
-        List<CloudifyDeployedTenant> tenantList = new ArrayList<CloudifyDeployedTenant>();
-        List<CloudifyExecution> cfyExecList = new ArrayList<CloudifyExecution>();
+        ECTransportModel result = null;
         try {
-            List<CloudifyTenant> cldfyTen = cloudifyClient.getTenants().items;
-            for (CloudifyTenant ct : (List<CloudifyTenant>) cldfyTen) {
-                cfyTenantDeployMapList = cloudifyClient.getTenantInfoFromDeploy(ct.name);
-                tenantList.addAll(((CloudifyDeployedTenantList) cfyTenantDeployMapList).items);
-            }
-            List<CloudifyDeployedTenant> currSrvcTenants = new ArrayList<CloudifyDeployedTenant>();
-
-            for (String serviceId : serviceList) {
-                for (CloudifyDeployedTenant deplTen : tenantList) {
-                    if (serviceId.equals(deplTen.id)) {
-                        currSrvcTenants.add(deplTen);
-                        break;
-                    }
-                }
-            }
-            // Get concise execution status for each of the tenant deployment items
-            boolean isHelmType = false;
-            boolean helmStatus = false;
-            for (CloudifyDeployedTenant deplItem : currSrvcTenants) {
-                CloudifyExecutionList execResults =
-                    cloudifyClient.getExecutionsSummary(deplItem.id, deplItem.tenant_name);
-                isHelmType = false;
-                helmStatus = false;
-                CloudifyBlueprintList bpList =
-                    cloudifyClient.getBlueprint(deplItem.id, deplItem.tenant_name);
-                Map<String, Object> bpPlan = bpList.items.get(0).plan;
-                Map<String, String> workflows = (Map<String, String>) bpPlan.get("workflows");
-                Map<String, String> pluginInfo =
-                    ((List<Map<String, String>>) bpPlan.get("deployment_plugins_to_install"))
-                        .get(0);
-                if (pluginInfo.get("name").equals("helm-plugin")) {
-                    isHelmType = true;
-                }
-                if (workflows.containsKey("status")) {
-                    helmStatus = true;
-                }
-                for (CloudifyExecution cfyExec : execResults.items) {
-                    if (cfyExec.workflow_id.equalsIgnoreCase("install")) {
-                        cfyExec.is_helm = isHelmType;
-                        cfyExec.helm_status = helmStatus;
-                        cfyExecList.add(cfyExec);
-                    }
-                }
+            if (tenant != null && tenant.length() > 0) {
+                result = cloudifyClient.getDeployment(id, tenant);
+            } else {
+                result = cloudifyClient.getDeployment(id);
             }
-            outboundJson = objectMapper.writeValueAsString(cfyExecList);
         } catch (HttpStatusCodeException e) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "Cloudify Manager");
             MDC.put("TargetServiceName", "Cloudify Manager");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting deployments failed!");
-            logger.error(EELFLoggerDelegate.errorLogger,
-                "getTenantStatusForService caught exception");
-            RestResponseError result = null;
-            result = new RestResponseError(
-                "getTenantStatusForService failed" + e.getResponseBodyAsString());
-            try {
-                outboundJson = objectMapper.writeValueAsString(result);
-            } catch (JsonProcessingException jpe) {
-                // Should never, ever happen
-                outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}";
-            }
-        } catch (Throwable t) {
+            MDC.put("ErrorDescription", "Getting deployment " + id + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getDeploymentById caught exception");
+            result = new RestResponseError(e.getResponseBodyAsString());
+        } catch (Exception t) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "Cloudify Manager");
             MDC.put("TargetServiceName", "Cloudify Manager");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting deployments failed!");
-            logger.error(EELFLoggerDelegate.errorLogger,
-                "getTenantStatusForService caught exception");
-            RestResponseError result = null;
-            result = new RestResponseError("getTenantStatusForService failed");
-            try {
-                outboundJson = objectMapper.writeValueAsString(result);
-            } catch (JsonProcessingException jpe) {
-                // Should never, ever happen
-                outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}";
-            }
+            MDC.put("ErrorDescription", "Getting deployment " + id + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getDeploymentById caught exception");
+            result = new RestResponseError("getDeploymentById failed", t);
         } finally {
             postLogAudit(request);
         }
-
-        return outboundJson;
+        return objectMapper.writeValueAsString(result);
     }
-
     /**
      * Gets and serves one page of executions:
      * <OL>
@@ -448,7 +1091,7 @@ public class CloudifyController extends DashboardRestrictedBaseController {
     @RequestMapping(value = { EXECUTIONS_PATH }, method = RequestMethod.GET, produces = "application/json")
     @ResponseBody
     public String getExecutionsByPage(HttpServletRequest request,
-        @RequestParam(value = "deployment_id", required = false) String deployment_id,
+        @RequestParam(value = "deployment_id", required = true) String deployment_id,
         @RequestParam(value = "status", required = false) String status,
         @RequestParam(value = "tenant", required = true) String tenant) throws Exception {
         preLogAudit(request);
@@ -460,7 +1103,7 @@ public class CloudifyController extends DashboardRestrictedBaseController {
             List<CloudifyExecution> itemList = new ArrayList<CloudifyExecution>();
             List<String> depIds = new ArrayList<>();
             if (deployment_id == null) {
-                CloudifyDeploymentList depList = cloudifyClient.getDeployments();
+                CloudifyDeploymentList depList = cloudifyClient.getDeployments(tenant, 100, 0);
                 for (CloudifyDeployment cd : depList.items)
                     depIds.add(cd.id);
             } else {
@@ -505,50 +1148,175 @@ public class CloudifyController extends DashboardRestrictedBaseController {
         return objectMapper.writeValueAsString(result);
     }
 
-    /**
-     * Gets the specified execution for one deployment.
-     * 
-     * It's not clear why the deployment ID is needed.
-     * 
-     * @param execution_id  Execution ID (path variable)
-     * @param deployment_id Deployment ID (query parameter)
-     * @param request       HttpServletRequest
-     * @return CloudifyExecutionList
-     * @throws Exception on serialization failure
-     */
-    @RequestMapping(value = { EXECUTIONS_PATH + "/{id}" }, method = RequestMethod.GET, produces = "application/json")
+    @SuppressWarnings("unchecked")
+    @RequestMapping(value = { EXECUTIONS_PATH + "/tenant" }, method = RequestMethod.GET, produces = "application/json")
     @ResponseBody
-    public String getExecutionByIdAndDeploymentId(@PathVariable("id") String execution_id,
-            @RequestParam("deployment_id") String deployment_id,
-            @RequestParam(value = "tenant", required = false) String tenant, HttpServletRequest request)
-            throws Exception {
+    public String getExecutionsPerTenant(HttpServletRequest request,
+        @RequestParam(value = "tenant", required = true) String tenant,
+        @RequestParam(value = "status", required = false) String status) throws Exception {
         preLogAudit(request);
         ECTransportModel result = null;
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        List<CloudifyTenant> cfyTenantList = null;
+        List<CloudifyTenant> myTenantsList = null;
         try {
+            List<CloudifyExecution> itemList = new ArrayList<CloudifyExecution>();
             if (tenant == null) {
-                throw new Exception("required tenant input missing");
+                // process all tenants that are relevant
+                lock.readLock().lock();
+                cfyTenantList = (List<CloudifyTenant>)getCacheManager().getObject(TENANTS_PATH);
+                lock.readLock().unlock();
+                if (cfyTenantList == null || cfyTenantList.isEmpty()) {
+                    cfyTenantList = (List<CloudifyTenant>)cloudifyClient.getTenants().items;
+                }               
+                myTenantsList = cfyTenantList;
+                
+                for (CloudifyTenant tenItem : myTenantsList) {
+                    CloudifyExecutionList exeList = 
+                        cloudifyClient.getExecutionsSummaryPerTenant(tenItem.name);
+                    // Filter down to specified status as needed
+                    if (status != null && !status.isEmpty()) {
+                        Iterator<CloudifyExecution> exeIter = exeList.items.iterator();
+                        while (exeIter.hasNext()) {
+                            CloudifyExecution ce = exeIter.next();
+                            if (!status.equals(ce.status))
+                                exeIter.remove();
+                        }
+                    }
+                    itemList.addAll(exeList.items);
+                }
+            } else {
+                CloudifyExecutionList exeList = cloudifyClient.getExecutionsSummaryPerTenant(tenant);
+                itemList.addAll(exeList.items);
+
+                // Filter down to specified status as needed
+                if (status != null && !status.isEmpty()) {
+                    Iterator<CloudifyExecution> exeIter = itemList.iterator();
+                    while (exeIter.hasNext()) {
+                        CloudifyExecution ce = exeIter.next();
+                        if (!status.equals(ce.status))
+                            exeIter.remove();
+                    }
+                }  
             }
-            result = cloudifyClient.getExecutions(deployment_id, tenant);
-        } catch (HttpStatusCodeException e) {
+            //Collections.sort(itemList, executionComparator);
+
+            // Paginate
+            final int pageNum = getRequestPageNumber(request);
+            final int pageSize = getRequestPageSize(request);
+            final int totalItems = itemList.size();
+            final int pageCount = (int) Math.ceil((double) totalItems / pageSize);
+            // Shrink if needed
+            if (totalItems > pageSize)
+                itemList = getPageOfList(pageNum, pageSize, itemList);
+            result = new RestResponsePage<>(totalItems, pageCount, itemList);
+        } catch (Exception t) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "Cloudify Manager");
             MDC.put("TargetServiceName", "Cloudify Manager");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription",
-                    "Getting executions " + execution_id + " for deployment " + deployment_id + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception");
-            result = new RestResponseError(e.getResponseBodyAsString());
+            MDC.put("ErrorDescription", "Getting executions failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getExecutionsByPage caught exception");
+            result = new RestResponseError("getExecutionsByPage failed", t);
+        } finally {
+            postLogAudit(request);
+        }
+        return objectMapper.writeValueAsString(result);
+    }
+
+    @SuppressWarnings("unchecked")
+    @RequestMapping(value = { EXECUTIONS_PATH + "/{id:.+}"}, method = RequestMethod.GET, produces = "application/json")
+    @ResponseBody
+    public String queryExecution(@PathVariable("id") String id, @RequestParam(value = "tenant", required = true) 
+        String tenant, HttpServletRequest request) throws Exception { 
+        preLogAudit(request);
+        ECTransportModel result = null;
+        try {
+            List<CloudifyExecution> itemList = new ArrayList<CloudifyExecution>();
+            CloudifyExecution cfyExecObj = cloudifyClient.getExecutionIdSummary(id, tenant);
+            itemList.add(cfyExecObj);
+            final int pageNum = getRequestPageNumber(request);
+            final int pageSize = getRequestPageSize(request);
+            final int totalItems = itemList.size();
+            final int pageCount = (int) Math.ceil((double) totalItems / pageSize);
+            // Shrink if needed
+            if (totalItems > pageSize)
+                itemList = getPageOfList(pageNum, pageSize, itemList);
+            result = new RestResponsePage<>(totalItems, pageCount, itemList);
         } catch (Exception t) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "Cloudify Manager");
             MDC.put("TargetServiceName", "Cloudify Manager");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription",
-                    "Getting executions " + execution_id + " for deployment " + deployment_id + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception");
-            result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t);
+            MDC.put("ErrorDescription", "Getting executions failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getExecutionsByPage caught exception");
+            result = new RestResponseError("getExecutionsByPage failed", t);
+        } finally {
+            postLogAudit(request);
+        }
+        return objectMapper.writeValueAsString(result);
+    }   
+    
+    @SuppressWarnings("unchecked")
+    @RequestMapping(value = { EXECUTIONS_PATH + "/active"}, method = RequestMethod.GET, produces = "application/json")
+    @ResponseBody
+    public String getActiveExecutions(HttpServletRequest request) throws Exception {
+        preLogAudit(request);
+        ECTransportModel result = null;
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        List<CloudifyTenant> cfyTenantList = null;
+        List<CloudifyTenant> myTenantsList = null;
+        String status = "started";
+        try {
+            List<CloudifyExecution> itemList = new ArrayList<CloudifyExecution>();
+            // process all tenants that are relevant
+            lock.readLock().lock();
+            cfyTenantList = (List<CloudifyTenant>)getCacheManager().getObject(TENANTS_PATH);
+            lock.readLock().unlock();
+            if (cfyTenantList == null || cfyTenantList.isEmpty()) {
+                cfyTenantList = (List<CloudifyTenant>)cloudifyClient.getTenants().items;
+            }               
+            myTenantsList = cfyTenantList;
+            
+            for (CloudifyTenant tenItem : myTenantsList) {
+                CloudifyExecutionList exeList = null;
+                try {
+                    exeList = 
+                    cloudifyClient.getExecutionsSummaryPerTenant(tenItem.name);
+                } catch (Exception e) {
+                    continue;
+                }
+                // Filter down to specified status as needed
+                Iterator<CloudifyExecution> exeIter = exeList.items.iterator();
+                while (exeIter.hasNext()) {
+                    CloudifyExecution ce = exeIter.next();
+                    if (!status.equals(ce.status))
+                        exeIter.remove();
+                }
+                itemList.addAll(exeList.items);
+            }
+            //Collections.sort(itemList, executionComparator);
+
+            // Paginate
+            final int pageNum = getRequestPageNumber(request);
+            final int pageSize = getRequestPageSize(request);
+            final int totalItems = itemList.size();
+            final int pageCount = (int) Math.ceil((double) totalItems / pageSize);
+            // Shrink if needed
+            if (totalItems > pageSize)
+                itemList = getPageOfList(pageNum, pageSize, itemList);
+            result = new RestResponsePage<>(totalItems, pageCount, itemList);
+        } catch (Exception t) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "Cloudify Manager");
+            MDC.put("TargetServiceName", "Cloudify Manager");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Getting executions failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getExecutionsByPage caught exception");
+            result = new RestResponseError("getExecutionsByPage failed", t);
         } finally {
             postLogAudit(request);
         }
@@ -641,7 +1409,7 @@ public class CloudifyController extends DashboardRestrictedBaseController {
         preLogAudit(request);
         ECTransportModel result = null;
         try {
-            if (!execution.workflow_id.equals("status")
+            if (!(execution.workflow_id.equals("status") || execution.workflow_id.equals("execute_operation"))
                 && !execution.getParameters().containsKey("node_instance_id")) {
                 // get the node instance ID for the deployment
                 String nodeInstId = "";
@@ -654,6 +1422,14 @@ public class CloudifyController extends DashboardRestrictedBaseController {
                 inParms.put("node_instance_id", nodeInstId);
                 execution.setParameters(inParms);
             }
+            if (execution.workflow_id.equals("upgrade")) {
+                String repo_user = 
+                cloudifyClient.getSecret("controller_helm_user", execution.getTenant()).value;
+                String repo_user_password = 
+                cloudifyClient.getSecret("controller_helm_password", execution.getTenant()).value;
+                execution.getParameters().put("repo_user", repo_user);
+                execution.getParameters().put("repo_user_password", repo_user_password);
+            }
             result = cloudifyClient.startExecution(execution);
         } catch (HttpStatusCodeException e) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
@@ -680,29 +1456,35 @@ public class CloudifyController extends DashboardRestrictedBaseController {
     }
 
     /**
-     * Processes request to create an execution based on a deployment.
+     * Cancels an execution.
      * 
-     * @param request   HttpServletRequest
-     * @param execution Execution model
-     * @return Information about the execution
+     * @param id           Execution ID
+     * @param deploymentId Deployment ID (not clear why this is needed)
+     * @param action       Action to perform (not clear why this is needed)
+     * @param request      HttpServletRequest
+     * @param response     HttpServletRequest
+     * @return Passes thru HTTP status code from remote endpoint; no body on success
      * @throws Exception on serialization failure
      */
-    @RequestMapping(value = { UPDATE_DEPLOYMENT_PATH }, method = RequestMethod.POST, produces = "application/json")
+    @RequestMapping(value = { EXECUTIONS_PATH + "/{id}" }, method = RequestMethod.POST, produces = "application/json")
     @ResponseBody
-    public String updateDeployment(HttpServletRequest request, @RequestBody CloudifyDeploymentUpdateRequest execution)
+    public String cancelExecution(@RequestHeader HttpHeaders headers, @PathVariable("id") String id,
+            @RequestBody Map<String, String> parameters, HttpServletRequest request, HttpServletResponse response)
             throws Exception {
         preLogAudit(request);
         ECTransportModel result = null;
+        List<String> tenant = null;
         try {
-            result = cloudifyClient.updateDeployment(execution);
+            tenant = headers.get("tenant");
+            result = cloudifyClient.cancelExecution(id, parameters, tenant.get(0));
         } catch (HttpStatusCodeException e) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "Cloudify Manager");
             MDC.put("TargetServiceName", "Cloudify Manager");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Updating deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception");
+            MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception");
             result = new RestResponseError(e.getResponseBodyAsString());
         } catch (Exception t) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
@@ -710,45 +1492,48 @@ public class CloudifyController extends DashboardRestrictedBaseController {
             MDC.put("TargetServiceName", "Cloudify Manager");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Updating Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception");
-            result = new RestResponseError("updateDeployment failed", t);
+            MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception");
+            result = new RestResponseError("cancelExecution failed on ID " + id, t);
         } finally {
             postLogAudit(request);
         }
-        return objectMapper.writeValueAsString(result);
+        if (result == null)
+            return null;
+        else
+            return objectMapper.writeValueAsString(result);
     }
 
     /**
-     * Cancels an execution.
+     * Gets the specified node-instances details
+     * 
+     * @query param deployment      deployment ID
+     * @query param tenant      tenant name
+     * @param request HttpServletRequest
+     * @return node instances as a string; or error.
+     * @throws Exception on serialization error
      * 
-     * @param id           Execution ID
-     * @param deploymentId Deployment ID (not clear why this is needed)
-     * @param action       Action to perform (not clear why this is needed)
-     * @param request      HttpServletRequest
-     * @param response     HttpServletRequest
-     * @return Passes thru HTTP status code from remote endpoint; no body on success
-     * @throws Exception on serialization failure
      */
-    @RequestMapping(value = { EXECUTIONS_PATH + "/{id}" }, method = RequestMethod.POST, produces = "application/json")
+    @RequestMapping(value = {"node-instances-data"},
+            method = RequestMethod.GET, produces = "application/json")
     @ResponseBody
-    public String cancelExecution(@RequestHeader HttpHeaders headers, @PathVariable("id") String id,
-            @RequestBody Map<String, String> parameters, HttpServletRequest request, HttpServletResponse response)
-            throws Exception {
+    public String getNodeInstanceDetails(
+            @RequestParam(value = "deployment", required = true) String deployment,
+            @RequestParam(value = "tenant", required = true) String tenant,
+            HttpServletRequest request) throws Exception {
         preLogAudit(request);
         ECTransportModel result = null;
-        List<String> tenant = null;
         try {
-            tenant = headers.get("tenant");
-            result = cloudifyClient.cancelExecution(id, parameters, tenant.get(0));
+            result = cloudifyClient.getNodeInstanceDetails(deployment, tenant);
         } catch (HttpStatusCodeException e) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "Cloudify Manager");
             MDC.put("TargetServiceName", "Cloudify Manager");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception");
+            MDC.put("ErrorDescription", "Getting node-instance with deploymentId " + deployment 
+                    + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getNodeInstance caught exception");
             result = new RestResponseError(e.getResponseBodyAsString());
         } catch (Exception t) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
@@ -756,16 +1541,62 @@ public class CloudifyController extends DashboardRestrictedBaseController {
             MDC.put("TargetServiceName", "Cloudify Manager");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception");
-            result = new RestResponseError("cancelExecution failed on ID " + id, t);
+            MDC.put("ErrorDescription", "Getting node-instance with deploymentId " + deployment 
+                    + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getNodeInstance caught exception");
+            result = new RestResponseError("getNodeInstance failed", t);
         } finally {
             postLogAudit(request);
         }
-        if (result == null)
-            return null;
-        else
-            return objectMapper.writeValueAsString(result);
+        return objectMapper.writeValueAsString(result);
+    }
+    
+    /**
+     * Gets the specified node-instances for viewing.
+     * 
+     * @param id      deployment ID
+     * @param request HttpServletRequest
+     * @return node instances as a string; or error.
+     * @throws Exception on serialization error
+     * 
+     */
+    @RequestMapping(value = { NODE_INSTANCES_PATH
+            + "/{deploymentId:.+}" }, method = RequestMethod.GET, produces = "application/yaml")
+    @ResponseBody
+    public String getNodeInstances(@PathVariable("deploymentId") String deploymentId,
+            @RequestParam(value = "tenant", required = true) String tenant,
+            HttpServletRequest request) throws Exception {
+        preLogAudit(request);
+        ECTransportModel result = null;
+        try {
+            if (tenant == null) {
+                throw new Exception("required tenant input missing");
+            }
+            result = cloudifyClient.getNodeInstances(deploymentId, tenant);
+        } catch (HttpStatusCodeException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "Cloudify Manager");
+            MDC.put("TargetServiceName", "Cloudify Manager");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Getting node-instance-id with deploymentId " + deploymentId 
+                    + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getNodeInstanceId caught exception");
+            result = new RestResponseError(e.getResponseBodyAsString());
+        } catch (Exception t) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "Cloudify Manager");
+            MDC.put("TargetServiceName", "Cloudify Manager");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Getting node-instance-id with deploymentId " + deploymentId 
+                    + " failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getNodeInstanceId caught exception");
+            result = new RestResponseError("getNodeInstanceId failed", t);
+        } finally {
+            postLogAudit(request);
+        }
+        return objectMapper.writeValueAsString(result);
     }
 
     /**
@@ -779,7 +1610,7 @@ public class CloudifyController extends DashboardRestrictedBaseController {
      * 
      */
     @RequestMapping(value = { NODE_INSTANCES_PATH
-            + "/{deploymentId}/{nodeId}" }, method = RequestMethod.GET, produces = "application/yaml")
+            + "/{deploymentId:.+}/{nodeId}" }, method = RequestMethod.GET, produces = "application/yaml")
     @ResponseBody
     public String getNodeInstanceId(@PathVariable("deploymentId") String deploymentId,
             @RequestParam(value = "tenant", required = true) String tenant, @PathVariable("nodeId") String nodeId,
@@ -818,7 +1649,7 @@ public class CloudifyController extends DashboardRestrictedBaseController {
     }
 
     @RequestMapping(value = {
-            DEPLOYMENTS_PATH + "/{deploymentId}/revisions" }, method = RequestMethod.GET, produces = "application/json")
+            DEPLOYMENTS_PATH + "/{deploymentId:.+}/revisions" }, method = RequestMethod.GET, produces = "application/json")
     @ResponseBody
     public String getDeploymentRevisions(@PathVariable("deploymentId") String deploymentId,
             @RequestParam(value = "tenant") String tenant, HttpServletRequest request) throws Exception {
@@ -853,6 +1684,51 @@ public class CloudifyController extends DashboardRestrictedBaseController {
         return objectMapper.writeValueAsString(result);
     }
 
+    /**
+     * Gets the cloudify plugins list
+     * 
+     * 
+     * @param request
+     *            HttpServletRequest
+     * @return list of CloudifyPlugin
+     * @throws Exception
+     *             on serialization failure
+     */
+    @SuppressWarnings("unchecked")
+    @RequestMapping(value = { PLUGINS_PATH }, method = RequestMethod.GET, produces = "application/json")
+    @ResponseBody
+    public String getPlugins( 
+            HttpServletRequest request) throws Exception {
+        preLogAudit(request);
+        ECTransportModel result = null;        
+        try {
+            List<CloudifyPlugin> resultsArr = cloudifyClient.getPlugins().items;
+            return objectMapper.writeValueAsString(resultsArr);
+        } catch (HttpStatusCodeException e) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "Cloudify Manager");
+            MDC.put("TargetServiceName", "Cloudify Manager");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Getting plugins failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getPlugins caught exception");
+            result = new RestResponseError(e.getResponseBodyAsString());
+            return objectMapper.writeValueAsString(result);
+        } catch (Throwable t) {
+            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
+            MDC.put("TargetEntity", "Cloudify Manager");
+            MDC.put("TargetServiceName", "Cloudify Manager");
+            MDC.put("ErrorCode", "300");
+            MDC.put("ErrorCategory", "ERROR");
+            MDC.put("ErrorDescription", "Getting plugins failed!");
+            logger.error(EELFLoggerDelegate.errorLogger, "getPlugins caught exception");
+            result = new RestResponseError("getSecret failed", t);
+            return objectMapper.writeValueAsString(result);
+        } finally {
+            postLogAudit(request);
+        }
+    }
+
     public void preLogAudit(HttpServletRequest request) {
         begin = new Date();
         MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin));
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CommonApiController.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/controller/CommonApiController.java
deleted file mode 100644 (file)
index bd53145..0000000
+++ /dev/null
@@ -1,1182 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-
-package org.onap.ccsdk.dashboard.controller;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.json.JSONObject;
-import org.onap.ccsdk.dashboard.domain.EcdComponent;
-import org.onap.ccsdk.dashboard.exceptions.BadRequestException;
-import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException;
-import org.onap.ccsdk.dashboard.exceptions.DownstreamException;
-import org.onap.ccsdk.dashboard.exceptions.ServerErrorException;
-import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException;
-import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException;
-import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeAlreadyDeactivatedException;
-import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenant;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecution;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList;
-import org.onap.ccsdk.dashboard.model.CloudifyTenant;
-import org.onap.ccsdk.dashboard.model.ECTransportModel;
-import org.onap.ccsdk.dashboard.model.RestResponseError;
-import org.onap.ccsdk.dashboard.model.RestResponsePage;
-import org.onap.ccsdk.dashboard.model.RestResponseSuccess;
-import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentInput;
-import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest;
-import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResource;
-import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResourceLinks;
-import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse;
-import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponseLinks;
-import org.onap.ccsdk.dashboard.model.inventory.Blueprint;
-import org.onap.ccsdk.dashboard.model.inventory.BlueprintResponse;
-import org.onap.ccsdk.dashboard.model.inventory.Service;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceType;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeServiceMap;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeUploadRequest;
-import org.onap.ccsdk.dashboard.rest.CloudifyClient;
-import org.onap.ccsdk.dashboard.rest.DeploymentHandlerClient;
-import org.onap.ccsdk.dashboard.rest.InventoryClient;
-import org.onap.ccsdk.dashboard.service.ControllerEndpointService;
-import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
-import org.onap.portalsdk.core.util.SystemProperties;
-import org.slf4j.MDC;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-import org.springframework.http.HttpHeaders;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestHeader;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.client.HttpStatusCodeException;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.core.type.TypeReference;
-
-@RestController
-@RequestMapping("/nb-api")
-public class CommonApiController extends DashboardRestrictedBaseController {
-    private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CommonApiController.class);
-
-    private static final String COMPONENTS_PATH = "components";
-    private static final String DEPLOYMENTS_PATH = "deployments";
-    private static final String SERVICE_TYPES_PATH = "blueprints";
-    private static final String EXECUTIONS_PATH = "executions";
-    private static final String DEP_TENANT_STATUS = "deployment-status";
-    private static final String TENANTS_PATH = "tenants";
-
-    @Autowired
-    private ControllerEndpointService controllerEndpointService;
-
-    @Autowired
-    InventoryClient inventoryClient;
-
-    @Autowired
-    DeploymentHandlerClient deploymentHandlerClient;
-
-    @Autowired
-    CloudifyClient cloudifyClient;
-
-    /**
-     * Enum for selecting an item type.
-     */
-    public enum InventoryDataItem {
-        SERVICES, SERVICE_TYPES, SERVICES_GROUPBY;
-    }
-
-    private static Date begin, end;
-
-    @RequestMapping(value = "/api-docs", method = RequestMethod.GET, produces = "application/json")
-    public Resource apiDocs() {
-        return new ClassPathResource("swagger.json");
-    }
-
-    @RequestMapping(value = { COMPONENTS_PATH }, method = RequestMethod.POST, produces = "application/json")
-    public String insertComponent(HttpServletRequest request, @RequestBody EcdComponent newComponent) throws Exception {
-        String outboundJson = null;
-        controllerEndpointService.insertComponent(newComponent);
-        RestResponseSuccess success = new RestResponseSuccess(
-                "Inserted new component with name " + newComponent.getCname());
-        outboundJson = objectMapper.writeValueAsString(success);
-        return outboundJson;
-    }
-
-    @RequestMapping(value = { COMPONENTS_PATH }, method = RequestMethod.GET, produces = "application/json")
-    public String getComponents(HttpServletRequest request) throws Exception {
-        List<EcdComponent> result = controllerEndpointService.getComponents();
-        return objectMapper.writeValueAsString(result);
-
-    }
-
-    /**
-     * gets the tenants list
-     * 
-     * @param request HttpServletRequest
-     * @return List of CloudifyDeployment objects
-     */
-    @SuppressWarnings("rawtypes")
-    @RequestMapping(value = { TENANTS_PATH }, method = RequestMethod.GET, produces = "application/json")
-    @ResponseBody
-    public String getTenants(HttpServletRequest request) throws Exception {
-        preLogAudit(request);
-        List itemList = cloudifyClient.getTenants().items;
-        final int totalItems = itemList.size();
-        final int pageSize = 20;
-        final int pageNum = 1;
-        final int pageCount = (int) Math.ceil((double) totalItems / pageSize);
-        if (totalItems > pageSize)
-            itemList = getPageOfList(pageNum, pageSize, itemList);
-        RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList);
-        String outboundJson = objectMapper.writeValueAsString(model);
-        return outboundJson;
-    }
-
-    /**
-     * Query status and tenant info for deployments
-     * 
-     */
-    @RequestMapping(value = { DEP_TENANT_STATUS }, method = RequestMethod.POST, produces = "application/json")
-    @ResponseBody
-    public String getTenantStatusForService(HttpServletRequest request, @RequestBody String[] serviceList)
-            throws Exception {
-        preLogAudit(request);
-        /*
-         * 1) Get all the tenant names 2) Get the deployment IDs per tenant for all the
-         * tenants, aggregate the deployments list 3) Get the input deployments list
-         * (screen input), filter the deployments list from step#2 4) For each item in
-         * the list from step#3, get the execution status info and generate the final
-         * response
-         */
-        String outboundJson = "";
-        ECTransportModel result = null;
-        List<CloudifyDeployedTenant> tenantList = new ArrayList<CloudifyDeployedTenant>();
-        List<CloudifyExecution> cfyExecList = new ArrayList<CloudifyExecution>();
-        try {
-            List<CloudifyTenant> cldfyTen = cloudifyClient.getTenants().items;
-            for (CloudifyTenant ct : (List<CloudifyTenant>) cldfyTen) {
-                result = cloudifyClient.getTenantInfoFromDeploy(ct.name);
-                tenantList.addAll(((CloudifyDeployedTenantList) result).items);
-            }
-            result = null;
-            List<CloudifyDeployedTenant> currSrvcTenants = new ArrayList<CloudifyDeployedTenant>();
-
-            for (String serviceId : serviceList) {
-                for (CloudifyDeployedTenant deplTen : tenantList) {
-                    if (serviceId.equals(deplTen.id)) {
-                        currSrvcTenants.add(deplTen);
-                        break;
-                    }
-                }
-            }
-            // Get concise execution status for each of the tenant deployment items
-            for (CloudifyDeployedTenant deplItem : currSrvcTenants) {
-                CloudifyExecutionList execResults =
-                    cloudifyClient.getExecutionsSummary(deplItem.id, deplItem.tenant_name);
-                for (CloudifyExecution cfyExec : execResults.items) {
-                    if (cfyExec.workflow_id.equalsIgnoreCase("install")) {
-                        cfyExecList.add(cfyExec);
-                    }
-                }
-            }
-            outboundJson = objectMapper.writeValueAsString(cfyExecList);
-        } catch (HttpStatusCodeException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting deployments failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getTenantStatusForService caught exception");
-            result = new RestResponseError(e.getResponseBodyAsString());
-            try {
-                outboundJson = objectMapper.writeValueAsString(result);
-            } catch (JsonProcessingException jpe) {
-                // Should never, ever happen
-                outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}";
-            }
-        } catch (Exception t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting deployments failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getTenantStatusForService caught exception");
-            result = new RestResponseError("getTenantStatusForService failed", t);
-            try {
-                outboundJson = objectMapper.writeValueAsString(result);
-            } catch (JsonProcessingException jpe) {
-                // Should never, ever happen
-                outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}";
-            }
-        } finally {
-            postLogAudit(request);
-        }
-
-        return outboundJson;
-    }
-
-    @RequestMapping(value = { SERVICE_TYPES_PATH }, method = RequestMethod.POST, produces = "application/json")
-    public String createBlueprint(HttpServletRequest request, @RequestBody ServiceTypeUploadRequest serviceTypeUplReq)
-            throws Exception {
-        String json = null;
-        try {
-            Blueprint.parse(serviceTypeUplReq.getBlueprintTemplate());
-            // InventoryClient inventoryClient = getInventoryClient();
-            Collection<String> serviceIds = new ArrayList<String>();
-            Collection<String> vnfTypes = new ArrayList<String>();
-            Collection<String> serviceLocations = new ArrayList<String>();
-            Optional<String> asdcServiceId = null;
-            Optional<String> asdcResourceId = null;
-            Optional<String> asdcServiceURL = null;
-
-            ServiceTypeRequest invSrvcTypeReq = new ServiceTypeRequest(serviceTypeUplReq.owner,
-                    serviceTypeUplReq.typeName, serviceTypeUplReq.typeVersion, serviceTypeUplReq.blueprintTemplate,
-                    serviceTypeUplReq.application, serviceTypeUplReq.component, serviceIds, vnfTypes, serviceLocations,
-                    asdcServiceId, asdcResourceId, asdcServiceURL);
-            ServiceType response = inventoryClient.addServiceType(invSrvcTypeReq);
-            // RestResponseSuccess success = new RestResponseSuccess("Uploaded new blueprint
-            // with name " + serviceTypeUplReq.typeName);
-            json = objectMapper.writeValueAsString(response);
-        } catch (BlueprintParseException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "DCAE Inventory");
-            MDC.put("TargetServiceName", "DCAE Inventory");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Updating service type failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "updateServiceTypeBlueprint caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError("Invalid blueprint format.", e));
-        } catch (HttpStatusCodeException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "DCAE Inventory");
-            MDC.put("TargetServiceName", "DCAE Inventory");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Updating service type failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "updateServiceTypeBlueprint caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getResponseBodyAsString()));
-        } catch (Throwable t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "DCAE Inventory");
-            MDC.put("TargetServiceName", "DCAE Inventory");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Updating service type failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "updateServiceTypeBlueprint caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError("updateServiceTypeBlueprint failed", t));
-        } finally {
-            postLogAudit(request);
-        }
-        return json;
-    }
-
-    @RequestMapping(value = { SERVICE_TYPES_PATH }, method = RequestMethod.GET, produces = "application/json")
-    public String getBlueprintsByPage(HttpServletRequest request) {
-        preLogAudit(request);
-        String json = null;
-        json = getItemListForPageWrapper(request, InventoryDataItem.SERVICE_TYPES, request.getParameter("name"),
-                request.getParameter("_include"));
-        postLogAudit(request);
-        return json;
-    }
-
-    @RequestMapping(value = {
-            SERVICE_TYPES_PATH + "/findByName" }, method = RequestMethod.GET, produces = "application/json")
-    public String queryBlueprintFilter(HttpServletRequest request) {
-        preLogAudit(request);
-        String json = null;
-        json = getItemListForPageWrapper(request, InventoryDataItem.SERVICE_TYPES, request.getParameter("name"),
-                request.getParameter("_include"));
-        postLogAudit(request);
-        return json;
-    }
-
-    @RequestMapping(value = {
-            DEPLOYMENTS_PATH + "/{deploymentId}" }, method = RequestMethod.GET, produces = "application/json")
-    public String getDeploymentsByPage(@PathVariable("deploymentId") String deploymentId, HttpServletRequest request) {
-        preLogAudit(request);
-        String json = null;
-        json = getItemListForPageWrapper(request, InventoryDataItem.SERVICES, deploymentId,
-                request.getParameter("_include"));
-        postLogAudit(request);
-        return json;
-    }
-
-    @RequestMapping(value = { DEPLOYMENTS_PATH }, method = RequestMethod.GET, produces = "application/json")
-    public String getAllDeploymentsByPage(HttpServletRequest request) {
-        preLogAudit(request);
-        String json = null;
-        json = getItemListForPageWrapper(request, InventoryDataItem.SERVICES, request.getParameter("deploymentId"),
-                request.getParameter("_include"));
-        postLogAudit(request);
-        return json;
-    }
-
-    /**
-     * Gets one page of the specified items. This method traps exceptions and
-     * constructs an appropriate JSON block to report errors.
-     * 
-     * @param request Inbound request
-     * @param option  Item type to get
-     * @return JSON with one page of objects; or an error.
-     */
-    protected String getItemListForPageWrapper(HttpServletRequest request, InventoryDataItem option, String searchBy,
-            String filters) {
-        preLogAudit(request);
-
-        String outboundJson = null;
-        try {
-            int pageNum = getRequestPageNumber(request);
-            int pageSize = getRequestPageSize(request);
-            outboundJson = getItemListForPage(option, pageNum, pageSize, searchBy, filters);
-        } catch (Exception ex) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "ECOMP Inventory");
-            MDC.put("TargetServiceName", "ECOMP Inventory");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting page of items failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getItemListForPageWrapper caught exception");
-            RestResponseError result = null;
-            if (ex instanceof HttpStatusCodeException)
-                result = new RestResponseError(((HttpStatusCodeException) ex).getResponseBodyAsString());
-            else
-                result = new RestResponseError("Failed to get " + option.name(), ex);
-            try {
-                outboundJson = objectMapper.writeValueAsString(result);
-            } catch (JsonProcessingException jpe) {
-                // Should never, ever happen
-                outboundJson = "{ \"error\" : \"" + jpe.toString() + "\"}";
-            }
-        } finally {
-            postLogAudit(request);
-        }
-        return outboundJson;
-    }
-
-    /**
-     * Gets one page of objects and supporting information via the REST client. On
-     * success, returns a PaginatedRestResponse object as String.
-     * 
-     * @param option   Specifies which item list type to get
-     * @param pageNum  Page number of results
-     * @param pageSize Number of items per browser page
-     * @return JSON block as String, see above.
-     * @throws Exception On any error; e.g., Network failure.
-     */
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    private String getItemListForPage(InventoryDataItem option, int pageNum, int pageSize, String searchBy,
-            String filters) throws Exception {
-        String outboundJson = "";
-        List itemList = null;
-
-        switch (option) {
-            case SERVICES:
-                itemList = inventoryClient.getServices().collect(Collectors.toList());
-                if (searchBy != null) {
-                    itemList = (List) itemList.stream()
-                        .filter(s -> ((Service) s).contains(searchBy)).collect(Collectors.toList());
-                }
-                // Get the tenant names for all the deployments from Cloudify/API handler
-                ECTransportModel result = null;
-                List<CloudifyDeployedTenant> tenantList = new ArrayList<CloudifyDeployedTenant>();
-                try {
-                    List<CloudifyTenant> cldfyTen = cloudifyClient.getTenants().items;
-                    for (CloudifyTenant ct : (List<CloudifyTenant>) cldfyTen) {
-                        result = cloudifyClient.getTenantInfoFromDeploy(ct.name);
-                        tenantList.addAll(((CloudifyDeployedTenantList) result).items);
-                    }
-                } catch (HttpStatusCodeException e) {
-                    MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-                    MDC.put("TargetEntity", "Cloudify Manager");
-                    MDC.put("TargetServiceName", "Cloudify Manager");
-                    MDC.put("ErrorCode", "300");
-                    MDC.put("ErrorCategory", "ERROR");
-                    MDC.put("ErrorDescription", "Getting deployments failed!");
-                    logger.error(EELFLoggerDelegate.errorLogger,
-                        "getTenantInfoFromDeploy caught exception");
-                    //result = new RestResponseError(e.getResponseBodyAsString());
-                } catch (Throwable t) {
-                    MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-                    MDC.put("TargetEntity", "Cloudify Manager");
-                    MDC.put("TargetServiceName", "Cloudify Manager");
-                    MDC.put("ErrorCode", "300");
-                    MDC.put("ErrorCategory", "ERROR");
-                    MDC.put("ErrorDescription", "Getting deployments failed!");
-                    logger.error(EELFLoggerDelegate.errorLogger,
-                        "getDeploymentById caught exception");
-                    //result = new RestResponseError("getTenantInfoFromDeploy failed", t);
-                } finally {
-
-            }
-
-            for (Service depl : (List<Service>) itemList) {
-                for (CloudifyDeployedTenant deplTen : tenantList) {
-                    if (depl.getDeploymentRef().equals(deplTen.id)) {
-                        depl.setTenant(deplTen.tenant_name);
-                        break;
-                    }
-                }
-            }
-            break;
-        case SERVICE_TYPES:
-            ServiceTypeQueryParams serviceQueryParams = null;
-            serviceQueryParams = new ServiceTypeQueryParams.Builder().onlyLatest(false).build();
-
-            itemList = inventoryClient.getServiceTypes(serviceQueryParams).collect(Collectors.toList());
-            List<BlueprintResponse> filterList = new ArrayList<BlueprintResponse>();
-
-            if (searchBy != null && searchBy.length() > 1) {
-                itemList = (List) itemList.stream().filter(s -> ((ServiceType) s).contains(searchBy))
-                        .collect(Collectors.toList());
-            }
-            if (filters != null && filters.length() > 0) {
-                String filterArr[] = filters.split(",");
-                for (ServiceType bp : (List<ServiceType>) itemList) {
-                    BlueprintResponse bpOut = new BlueprintResponse();
-                    for (String fltr : filterArr) {
-                        switch (fltr) {
-                        case "typeName":
-                            bpOut.setTypeName(bp.getTypeName());
-                            break;
-                        case "typeId":
-                            if (bp.getTypeId().isPresent()) {
-                            bpOut.setTypeId(bp.getTypeId().get());
-                            }
-                            break;
-                        case "typeVersion":
-                            bpOut.setTypeVersion(bp.getTypeVersion());
-                            break;
-                        default:
-                            break;
-                        }
-                    }
-                    filterList.add(bpOut);
-                }
-                if (filterList.size() > 0) {
-                    itemList.clear();
-                    itemList.addAll(filterList);
-                }
-            }
-            break;
-        default:
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "DCAE Inventory");
-            MDC.put("TargetServiceName", "DCAE Inventory");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting page of items failed!");
-            throw new Exception("getItemListForPage failed: unimplemented case: " + option.name());
-        }
-        // Shrink if needed
-        final int totalItems = itemList.size();
-        final int pageCount = (int) Math.ceil((double) totalItems / pageSize);
-        if (totalItems > pageSize)
-            itemList = getPageOfList(pageNum, pageSize, itemList);
-
-        RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList);
-        outboundJson = objectMapper.writeValueAsString(model);
-
-        return outboundJson;
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    private String getBlueprintTypeId(String searchBy, Optional<Integer> version, String typeId) throws Exception {
-
-        // InventoryClient inventoryClient = getInventoryClient();
-        ServiceTypeQueryParams serviceQueryParams = null;
-
-        if (version.isPresent()) {
-            serviceQueryParams = new ServiceTypeQueryParams.Builder().typeName(searchBy).onlyLatest(false).build();
-        } else {
-            serviceQueryParams = new ServiceTypeQueryParams.Builder().typeName(searchBy).build();
-        }
-
-        List itemList = inventoryClient.getServiceTypes(serviceQueryParams).collect(Collectors.toList());
-
-        if (version.isPresent()) {
-            itemList = (List) itemList.stream().filter(s -> ((ServiceType) s).contains(version.get().toString()))
-                    .collect(Collectors.toList());
-        }
-        Optional<String> bpId = Optional.of("");
-        if (typeId != null && typeId.equals("typeId")) {
-            ServiceType item = (ServiceType) ((List) itemList).get(0);
-            bpId = item.getTypeId();
-        }
-        return bpId.get();
-    }
-
-    /**
-     * Query the installed helm package revisions from cloudify
-     * 
-     * @param deploymentId
-     * @param tenant
-     * @param request
-     * @return
-     * @throws Exception
-     */
-    @RequestMapping(value = {
-            DEPLOYMENTS_PATH + "/{deploymentId}/revisions" }, method = RequestMethod.GET, produces = "application/json")
-    public String getDeploymentRevisions(@PathVariable("deploymentId") String deploymentId,
-            @RequestParam(value = "tenant") String tenant, HttpServletRequest request) throws Exception {
-        preLogAudit(request);
-        ECTransportModel result = null;
-        try {
-            if (tenant == null) {
-                throw new Exception("tenant name is missing");
-            }
-            result = cloudifyClient.getNodeInstanceVersion(deploymentId, tenant);
-        } catch (HttpStatusCodeException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception");
-            result = new RestResponseError(e.getResponseBodyAsString());
-        } catch (Throwable t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception");
-            result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t);
-        } finally {
-            postLogAudit(request);
-        }
-        return objectMapper.writeValueAsString(result);
-    }
-
-    /**
-     * Query inputs used to create a deployment
-     * 
-     * @param deploymentId
-     * @param tenant
-     * @param request
-     * @return
-     * @throws Exception
-     */
-    @RequestMapping(value = {
-            DEPLOYMENTS_PATH + "/{deploymentId}/inputs" }, method = RequestMethod.GET, produces = "application/json")
-    public String getDeploymentInputs(@PathVariable("deploymentId") String deploymentId,
-        @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request)
-        throws Exception {
-        preLogAudit(request);
-        ECTransportModel result = null;
-        try {
-            if (tenant == null) {
-                throw new Exception("tenant name is missing");
-            }
-            result = cloudifyClient.getDeploymentInputs(deploymentId, tenant);
-        } catch (HttpStatusCodeException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception");
-            result = new RestResponseError(e.getResponseBodyAsString());
-        } catch (Throwable t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception");
-            result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t);
-        } finally {
-            postLogAudit(request);
-        }
-        return objectMapper.writeValueAsString(result);
-    }
-
-    /**
-     * Create an upgrade/rollback workflow execution for a deployment.
-     * 
-     * @param request   HttpServletRequest
-     * @param execution Execution model
-     * @return Information about the execution
-     * @throws Exception on serialization failure
-     */
-    @RequestMapping(value = {
-            DEPLOYMENTS_PATH + "/{deploymentId}" }, method = RequestMethod.PUT, produces = "application/json")
-    public String modifyDeployment(@PathVariable("deploymentId") String deploymentId, HttpServletRequest request,
-            InputStream upgParams) throws Exception {
-        preLogAudit(request);
-        ECTransportModel result = null;
-        try {
-            String nodeInstId = "";
-            Map<String, Object> parameters = objectMapper.readValue(upgParams,
-                    new TypeReference<Map<String, Object>>() {
-                    });
-            String tenant = (String) parameters.get("tenant");
-            String workflow = (String) parameters.get("workflow");
-            parameters.remove("tenant");
-            parameters.remove("workflow");
-            // get the node instance ID for the deployment
-            CloudifyNodeInstanceIdList nodeInstList =
-                cloudifyClient.getNodeInstanceId(deploymentId, tenant);
-            if (nodeInstList != null) {
-                nodeInstId = nodeInstList.items.get(0).id;
-            }
-            parameters.put("node_instance_id", nodeInstId);
-            CloudifyExecutionRequest execution = new CloudifyExecutionRequest(deploymentId,
-                workflow, false, false, tenant, parameters);
-            result = cloudifyClient.startExecution(execution);
-        } catch (HttpStatusCodeException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Updating deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception");
-            result = new RestResponseError(e.getResponseBodyAsString());
-        } catch (Throwable t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Updating Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "updateDeployment caught exception");
-            result = new RestResponseError("updateDeployment failed", t);
-        } finally {
-            postLogAudit(request);
-        }
-        return objectMapper.writeValueAsString(result);
-    }
-
-    @RequestMapping(value = {
-            SERVICE_TYPES_PATH + "/{typeid}" + "/services" }, method = RequestMethod.GET, produces = "application/json")
-    public String getServicesForType(HttpServletRequest request, @PathVariable("typeid") String typeId)
-            throws Exception {
-        preLogAudit(request);
-        List<ServiceTypeServiceMap> result = new ArrayList<ServiceTypeServiceMap>();
-        // InventoryClient inventoryClient = getInventoryClient();
-        ServiceQueryParams qryParams = new ServiceQueryParams.Builder().typeId(typeId).build();
-        ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams);
-        ServiceTypeServiceMap srvcMap = new ServiceTypeServiceMap(typeId, srvcRefs);
-        result.add(srvcMap);
-        return objectMapper.writeValueAsString(result);
-    }
-
-    @RequestMapping(value = { DEPLOYMENTS_PATH }, method = RequestMethod.POST, produces = "application/json")
-    public String createDeployment(HttpServletRequest request, @RequestBody DeploymentInput deploymentRequestObject)
-            throws Exception {
-        preLogAudit(request);
-        String json = null;
-        StringBuffer status = new StringBuffer();
-        // Optional<String> bpId = Optional.empty();
-        Optional<Integer> bpVersion = null;
-        String srvcTypeId = null;
-        String bpName = deploymentRequestObject.getBlueprintName();
-        String cName = deploymentRequestObject.getComponent();
-        String tag = deploymentRequestObject.getTag();
-        String depName = cName + "_" + tag;
-
-        if (deploymentRequestObject.getBlueprintVersion().isPresent()) {
-            bpVersion = deploymentRequestObject.getBlueprintVersion();
-        }
-        if (deploymentRequestObject.getBlueprintId().isPresent()) {
-            srvcTypeId = deploymentRequestObject.getBlueprintId().get();
-            // srvcTypeId = bpId.get();
-        }
-        if (srvcTypeId == null) {
-            // get the serviceTypeId from inventory using the blueprint name
-            try {
-                srvcTypeId = getBlueprintTypeId(bpName, bpVersion, "typeId");
-            } catch (Exception ex) {
-                MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-                MDC.put("TargetEntity", "ECOMP Inventory");
-                MDC.put("TargetServiceName", "ECOMP Inventory");
-                MDC.put("ErrorCode", "300");
-                MDC.put("ErrorCategory", "ERROR");
-                MDC.put("ErrorDescription", "Getting blueprint ID failed!");
-                logger.error(EELFLoggerDelegate.errorLogger, "getItemListForPageWrapper caught exception");
-                RestResponseError result = null;
-                if (ex instanceof HttpStatusCodeException)
-                    result = new RestResponseError(((HttpStatusCodeException) ex).getResponseBodyAsString());
-                else
-                    result = new RestResponseError("Failed to get blueprint", ex);
-                try {
-                    json = objectMapper.writeValueAsString(result);
-                } catch (JsonProcessingException jpe) {
-                    // Should never, ever happen
-                    json = "{ \"error\" : \"" + jpe.toString() + "\"}";
-                }
-                return json;
-            } finally {
-                postLogAudit(request);
-            }
-        }
-        try {
-            DeploymentResponse resp =
-                deploymentHandlerClient.putDeployment(depName, deploymentRequestObject.getTenant(),
-                    new DeploymentRequest(srvcTypeId, deploymentRequestObject.getInputs()));
-            DeploymentResponseLinks deplLinks = resp.getLinks();
-            String deplStatus = deplLinks.getStatus();
-            if (!deplStatus.contains("cfy_tenant")) {
-                deplStatus = deplStatus + "?cfy_tenant_name=" + deploymentRequestObject.getTenant();
-            }
-            String self = request.getRequestURL().append("/").append(depName).toString();
-            status.append(self).append("/executions?tenant=").append(deploymentRequestObject.getTenant());
-            DeploymentResource deplRsrc = new DeploymentResource(depName,
-                    new DeploymentResourceLinks(self, deplStatus, status.toString()));
-            JSONObject statObj = new JSONObject(deplRsrc);
-            json = statObj.toString();
-        } catch (BadRequestException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (ServiceAlreadyExistsException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (ServerErrorException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (DownstreamException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (Throwable t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError("putDeployment failed", t));
-        } finally {
-            postLogAudit(request);
-        }
-        return json;
-    }
-
-    @RequestMapping(value = {
-            DEPLOYMENTS_PATH + "/{deploymentId}/update" }, method = RequestMethod.PUT, produces = "application/json")
-    public String updateDeployment(@PathVariable("deploymentId") String deploymentId, HttpServletRequest request,
-            @RequestBody DeploymentInput deploymentRequestObject) throws Exception {
-        preLogAudit(request);
-        String json = null;
-        String srvcTypeId = "";
-        Optional<Integer> bpVersion = null;
-        String bpName = deploymentRequestObject.getBlueprintName();
-        if (deploymentRequestObject.getBlueprintVersion().isPresent()) {
-            bpVersion = deploymentRequestObject.getBlueprintVersion();
-        }
-        // get the serviceTypeId from inventory using the blueprint name
-        try {
-            srvcTypeId = getBlueprintTypeId(bpName, bpVersion, "typeId");
-        } catch (Exception ex) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "ECOMP Inventory");
-            MDC.put("TargetServiceName", "ECOMP Inventory");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting blueprint ID failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getItemListForPageWrapper caught exception");
-            RestResponseError result = null;
-            if (ex instanceof HttpStatusCodeException)
-                result = new RestResponseError(((HttpStatusCodeException) ex).getResponseBodyAsString());
-            else
-                result = new RestResponseError("Failed to get blueprint", ex);
-            try {
-                json = objectMapper.writeValueAsString(result);
-            } catch (JsonProcessingException jpe) {
-                // Should never, ever happen
-                json = "{ \"error\" : \"" + jpe.toString() + "\"}";
-            }
-            return json;
-        } finally {
-            postLogAudit(request);
-        }
-        try {
-            json = objectMapper.writeValueAsString(deploymentHandlerClient.updateDeployment(
-                deploymentId, deploymentRequestObject.getTenant(),
-                new DeploymentRequest(srvcTypeId, deploymentRequestObject.getInputs())));
-        } catch (BadRequestException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (ServiceAlreadyExistsException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (ServerErrorException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (DownstreamException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (JsonProcessingException jpe) {
-            // Should never, ever happen
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception");
-            json = "{ \"error\" : \"" + jpe.toString() + "\"}";
-        } catch (Throwable t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deployment failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "putDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError("putDeployment failed", t));
-        } finally {
-            postLogAudit(request);
-        }
-        return json;
-    }
-
-    /**
-     * Gets the executions for one deployment.
-     * 
-     * 
-     * @param deployment_id Deployment ID (query parameter)
-     * @param request       HttpServletRequest
-     * @return CloudifyExecutionList
-     * @throws Exception on serialization failure
-     */
-    @RequestMapping(value = { DEPLOYMENTS_PATH + "/{deploymentId}" + "/"
-            + EXECUTIONS_PATH }, method = RequestMethod.GET, produces = "application/json")
-    @ResponseBody
-    public String getExecutionByDeploymentId(@PathVariable("deploymentId") String deploymentId,
-            @RequestParam(value = "tenant", required = true) String tenant, HttpServletRequest request)
-            throws Exception {
-        preLogAudit(request);
-        ECTransportModel result = null;
-        try {
-            if (tenant == null) {
-                throw new Exception("tenant name is missing");
-            }
-            result = cloudifyClient.getExecutionsSummary(deploymentId, tenant);
-        } catch (HttpStatusCodeException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception");
-            result = new RestResponseError(e.getResponseBodyAsString());
-        } catch (Throwable t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Getting executions for deployment " + deploymentId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "getExecutionByIdAndDeploymentId caught exception");
-            result = new RestResponseError("getExecutionByIdAndDeploymentId failed", t);
-        } finally {
-            postLogAudit(request);
-        }
-        return objectMapper.writeValueAsString(result);
-    }
-
-    /**
-     * Deletes the specified blueprint.
-     *
-     * @param id       Blueprint ID
-     * @param request  HttpServletRequest
-     * @param response HttpServletResponse
-     * @return status code on success; error on failure.
-     * @throws Exception On serialization failure
-     */
-    @RequestMapping(value = {
-            SERVICE_TYPES_PATH + "/{typeid}" }, method = RequestMethod.DELETE, produces = "application/json")
-    @ResponseBody
-    public String deleteBlueprint(@PathVariable("typeid") String typeId, HttpServletRequest request,
-            HttpServletResponse response) throws Exception {
-        preLogAudit(request);
-        String json = "{\"202\": \"OK\"}";
-        try {
-            // InventoryClient inventoryClient = getInventoryClient();
-            ServiceQueryParams qryParams = new ServiceQueryParams.Builder().typeId(typeId).build();
-            ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams);
-            if (srvcRefs != null && srvcRefs.totalCount > 0) {
-                throw new Exception("Services exist for the service type template, delete not permitted");
-            }
-            inventoryClient.deleteServiceType(typeId);
-        } catch (ServiceTypeNotFoundException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "DCAE Inventory");
-            MDC.put("TargetServiceName", "DCAE Inventory");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (ServiceTypeAlreadyDeactivatedException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "DCAE Inventory");
-            MDC.put("TargetServiceName", "DCAE Inventory");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (Throwable t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "DCAE Inventory");
-            MDC.put("TargetServiceName", "DCAE Inventory");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deleteBlueprint caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError("deleteBlueprint failed", t));
-        } finally {
-            postLogAudit(request);
-        }
-        return json;
-    }
-
-    /**
-     * Un-deploy an application or service
-     * 
-     * @param deploymentId
-     * @param request
-     * @param tenant
-     * @param response
-     * @return
-     * @throws Exception
-     */
-    @RequestMapping(
-        value = {DEPLOYMENTS_PATH + "/{deploymentId}"},
-        method = RequestMethod.DELETE,
-        produces = "application/json")
-    public String deleteDeployment(@PathVariable("deploymentId") String deploymentId,
-        HttpServletRequest request, @RequestParam(value = "tenant", required = true) String tenant,
-        HttpServletResponse response) throws Exception {
-        preLogAudit(request);
-        String json = null;
-        StringBuffer status = new StringBuffer();
-        try {
-            if (tenant == null) {
-                throw new Exception("tenant name is missing");
-            }
-            deploymentHandlerClient.deleteDeployment(deploymentId, tenant);
-            String self = request.getRequestURL().toString().split("\\?")[0];
-            status.append(self).append("/executions?tenant=").append(tenant);
-            DeploymentResource deplRsrc = new DeploymentResource(deploymentId,
-                    new DeploymentResourceLinks(self, "", status.toString()));
-            JSONObject statObj = new JSONObject(deplRsrc);
-            json = statObj.toString();
-        } catch (BadRequestException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (ServerErrorException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (DownstreamException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (DeploymentNotFoundException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (Throwable t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Deployment Handler");
-            MDC.put("TargetServiceName", "Deployment Handler");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting deployment " + deploymentId + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deleteDeployment caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError("deleteDeployment failed", t));
-        } finally {
-            postLogAudit(request);
-        }
-        return json;
-    }
-
-    /**
-     * Cancels an execution.
-     * 
-     * @param id           Execution ID
-     * @param deploymentId Deployment ID (not clear why this is needed)
-     * @param action       Action to perform (not clear why this is needed)
-     * @param request      HttpServletRequest
-     * @param response     HttpServletRequest
-     * @return Passes thru HTTP status code from remote endpoint; no body on success
-     * @throws Exception on serialization failure
-     */
-    @RequestMapping(value = { EXECUTIONS_PATH + "/{id}" }, method = RequestMethod.POST, produces = "application/json")
-    @ResponseBody
-    public String cancelExecution(@RequestHeader HttpHeaders headers, @PathVariable("id") String id,
-            @RequestBody Map<String, String> parameters, HttpServletRequest request, HttpServletResponse response)
-            throws Exception {
-        preLogAudit(request);
-        ECTransportModel result = null;
-        List<String> tenant = null;
-        try {
-            tenant = headers.get("tenant");
-            result = cloudifyClient.cancelExecution(id, parameters, tenant.get(0));
-        } catch (HttpStatusCodeException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception");
-            result = new RestResponseError(e.getResponseBodyAsString());
-        } catch (Throwable t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Cloudify Manager");
-            MDC.put("TargetServiceName", "Cloudify Manager");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Cancelling execution " + id + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "cancelExecution caught exception");
-            result = new RestResponseError("cancelExecution failed on ID " + id, t);
-        } finally {
-            postLogAudit(request);
-        }
-        if (result == null)
-            return null;
-        else
-            return objectMapper.writeValueAsString(result);
-    }
-
-    private void preLogAudit(HttpServletRequest request) {
-        begin = new Date();
-        MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin));
-        MDC.put(SystemProperties.METRICSLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin));
-        MDC.put(SystemProperties.STATUS_CODE, "COMPLETE");
-    }
-
-    private void postLogAudit(HttpServletRequest request) {
-        end = new Date();
-        MDC.put("AlertSeverity", "0");
-        MDC.put("TargetEntity", "Deployment Handler");
-        MDC.put("TargetServiceName", "Deployment Handler");
-        MDC.put(SystemProperties.AUDITLOG_END_TIMESTAMP, logDateFormat.format(end));
-        MDC.put(SystemProperties.METRICSLOG_END_TIMESTAMP, logDateFormat.format(end));
-        //MDC.put(SystemProperties.MDC_TIMER, Long.toString((end.getTime() - begin.getTime())));
-        logger.info(EELFLoggerDelegate.auditLogger, request.getMethod() + request.getRequestURI());
-        logger.info(EELFLoggerDelegate.metricsLogger, request.getMethod() + request.getRequestURI());
-    }
-}
index 28f7520..25ab3fd 100644 (file)
@@ -29,15 +29,15 @@ import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
 
-import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration;
-import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration.EndpointCheck;
-import org.onap.ccsdk.dashboard.model.ConsulNodeInfo;
-import org.onap.ccsdk.dashboard.model.ConsulServiceHealth;
-import org.onap.ccsdk.dashboard.model.ConsulServiceInfo;
 import org.onap.ccsdk.dashboard.model.ECTransportModel;
 import org.onap.ccsdk.dashboard.model.RestResponseError;
 import org.onap.ccsdk.dashboard.model.RestResponsePage;
 import org.onap.ccsdk.dashboard.model.RestResponseSuccess;
+import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration;
+import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration.EndpointCheck;
+import org.onap.ccsdk.dashboard.model.consul.ConsulNodeInfo;
+import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth;
+import org.onap.ccsdk.dashboard.model.consul.ConsulServiceInfo;
 import org.onap.ccsdk.dashboard.rest.ConsulClient;
 import org.onap.portalsdk.core.domain.User;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
@@ -333,105 +333,6 @@ public class ConsulController extends DashboardRestrictedBaseController {
         return json;
     }
 
-    /**
-     * Processes request to register a service for health checks.
-     * 
-     * @param request      HttpServletRequest
-     * @param registration Consul service registration
-     * @return URI of the newly registered resource
-     * @throws Exception on serialization error
-     */
-    @RequestMapping(value = { "/register" }, method = RequestMethod.POST, produces = "application/json")
-    @ResponseBody
-    public String registerService(HttpServletRequest request, @RequestBody ConsulHealthServiceRegistration registration)
-            throws Exception {
-        preLogAudit(request);
-        ECTransportModel result = null;
-        try {
-            if (registration.services == null) {
-                throw new Exception("services[] tag is mandatory");
-            }
-
-            List<EndpointCheck> checks = registration.services.get(0).checks;
-            String service_name = registration.services.get(0).name;
-            String service_port = registration.services.get(0).port;
-            String service_address = registration.services.get(0).address;
-
-            if (checks == null || service_port.isEmpty() || service_address.isEmpty() || service_name.isEmpty()) {
-                throw new Exception("fields : [checks[], port, address, name] are mandatory");
-            }
-            for (EndpointCheck check : checks) {
-                if (check.endpoint.isEmpty() || check.interval.isEmpty()) {
-                    throw new Exception("Required fields : [endpoint, interval] in checks");
-                }
-            }
-            result = new RestResponseSuccess(consulClient.registerService(registration));
-        } catch (HttpStatusCodeException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Consul");
-            MDC.put("TargetServiceName", "Consul");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Registering service failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "registerService caught exception");
-            result = new RestResponseError(e.getResponseBodyAsString());
-        } catch (Exception t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Consul");
-            MDC.put("TargetServiceName", "Consul");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Registering service failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "registerService caught exception");
-            result = new RestResponseError("registerService failed", t);
-        } finally {
-            postLogAudit(request);
-        }
-        return objectMapper.writeValueAsString(result);
-    }
-
-    /**
-     * Processes request to deregister a service for health checks.
-     * 
-     * @param request     HttpServletRequest
-     * @param serviceName Consul service name to deregister
-     * @return Success or error indicator
-     * @throws Exception on serialization error
-     */
-    @RequestMapping(value = {
-            "/deregister" + "/{serviceName}" }, method = RequestMethod.POST, produces = "application/json")
-    @ResponseBody
-    public String deregisterService(HttpServletRequest request, @PathVariable String serviceName) throws Exception {
-        preLogAudit(request);
-        ECTransportModel result = null;
-        try {
-            int code = consulClient.deregisterService(serviceName);
-            result =
-                new RestResponseSuccess("Deregistration yielded code " + Integer.toString(code));
-        } catch (HttpStatusCodeException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Consul");
-            MDC.put("TargetServiceName", "Consul");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "De-registering service " + serviceName + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deregisterService caught exception");
-            result = new RestResponseError(e.getResponseBodyAsString());
-        } catch (Throwable t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "Consul");
-            MDC.put("TargetServiceName", "Consul");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "De-registering service " + serviceName + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deregisterService caught exception");
-            result = new RestResponseError("deregisterService failed", t);
-        } finally {
-            postLogAudit(request);
-        }
-        return objectMapper.writeValueAsString(result);
-    }
-
     public void preLogAudit(HttpServletRequest request) {
         begin = new Date();
         MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin));
index cccd8f6..263c3d0 100644 (file)
  *******************************************************************************/
 package org.onap.ccsdk.dashboard.controller;
 
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.stream.Collectors;
-
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
 
-import org.onap.ccsdk.dashboard.domain.EcdComponent;
-import org.onap.ccsdk.dashboard.model.EcdAppComponent;
-import org.onap.ccsdk.dashboard.model.RestResponseError;
-import org.onap.ccsdk.dashboard.model.RestResponseSuccess;
-import org.onap.ccsdk.dashboard.service.ControllerEndpointService;
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.onap.portalsdk.core.util.SystemProperties;
 import org.slf4j.MDC;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
 import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.ResponseBody;
@@ -61,19 +49,14 @@ public class DashboardHomeController extends DashboardRestrictedBaseController {
 
     private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(DashboardHomeController.class);
 
-    @Autowired
-    private ControllerEndpointService controllerEndpointService;
-
     /**
      * For general use in these methods
      */
     private final ObjectMapper mapper;
 
     private static Date begin, end;
-    private static final String COMPONENTS_PATH = "components";
-    private static final String USER_APPS_PATH = "user-apps";
     private static final String APP_LABEL = "app-label";
-
+    
     /**
      * Never forget that Spring autowires fields AFTER the constructor is called.
      */
@@ -93,79 +76,10 @@ public class DashboardHomeController extends DashboardRestrictedBaseController {
         return new ModelAndView("ecd_home_tdkey");
     }
 
-    /**
-     * Gets the available blueprint component names
-     * 
-     * @param request HttpServletRequest
-     * @return List of component name strings, or an error on failure
-     */
-    @RequestMapping(
-        value = {COMPONENTS_PATH},
-        method = RequestMethod.GET,
-        produces = "application/json")
+    @RequestMapping(value = "/api-docs", method = RequestMethod.GET, produces = "application/json")
     @ResponseBody
-    public String getComponents(HttpServletRequest request) {
-        preLogAudit(request);
-        String outboundJson = "";
-        try {
-            HttpSession session = request.getSession(true);
-            @SuppressWarnings("unchecked")
-            Set<String> userApps = (Set<String>) session.getAttribute("authComponents");
-            if (userApps == null) {
-                userApps = new TreeSet<String>();
-            }
-            List<EcdComponent> filterList = new ArrayList<EcdComponent>();
-            List<EcdAppComponent> ecdApps = new ArrayList<EcdAppComponent>();
-
-            List<EcdComponent> dbResult = controllerEndpointService.getComponents();
-
-            List dcaeCompList = (List) dbResult.stream()
-                .filter(s -> ((EcdComponent) s).contains("dcae")).collect(Collectors.toList());
-
-            if (!userApps.isEmpty()) { // non-admin role level
-                for (String userRole : userApps) {
-                    if (userRole.equalsIgnoreCase("dcae")) {
-                        if (dcaeCompList != null && !dcaeCompList.isEmpty()) {
-                            EcdAppComponent dcaeAppComponent =
-                                new EcdAppComponent("DCAE", dcaeCompList);
-                            ecdApps.add(dcaeAppComponent);
-                        }
-                    } else {
-                        List tmpItemList = (List) dbResult.stream()
-                            .filter(s -> ((EcdComponent) s).contains(userRole))
-                            .collect(Collectors.toList());
-                        if (tmpItemList != null) {
-                            logger.debug(">>>> adding filtered items");
-                            filterList.addAll(tmpItemList);
-                        }
-                    }
-                }
-                if (!filterList.isEmpty()) {
-                    EcdAppComponent ecdAppComponent = new EcdAppComponent("ECOMP", filterList);
-                    ecdApps.add(ecdAppComponent);
-                }
-            } else {
-                // lookup "dcae" in the db component list
-                if (dcaeCompList != null && !dcaeCompList.isEmpty()) {
-                    EcdAppComponent dcaeAppComponent = new EcdAppComponent("DCAE", dcaeCompList);
-                    ecdApps.add(dcaeAppComponent);
-                }
-            }
-            outboundJson = mapper.writeValueAsString(ecdApps);
-        } catch (Exception ex) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "DashboardHomeController");
-            MDC.put("TargetServiceName", "DashboardHomeController");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Get components failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "Failed to get components list");
-            RestResponseError response = new RestResponseError("Failed to get components list", ex);
-            outboundJson = response.toJson();
-        } finally {
-            postLogAudit(request);
-        }
-        return outboundJson;
+    public Resource apiDocs() {
+        return new ClassPathResource("swagger.json");
     }
 
     /**
@@ -178,70 +92,7 @@ public class DashboardHomeController extends DashboardRestrictedBaseController {
         return mapper.writeValueAsString(
             DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_IN_ENV, "NA"));
     }
-
-    /**
-     * Gets the application name(s) for the authenticated user
-     * 
-     * @param request HttpServletRequest
-     * @return List of component name strings, or an error on failure
-     */
-    @SuppressWarnings("unchecked")
-    @RequestMapping(
-        value = {USER_APPS_PATH},
-        method = RequestMethod.GET,
-        produces = "application/json")
-    @ResponseBody
-    public String getUserApps(HttpServletRequest request) {
-        preLogAudit(request);
-        String outboundJson = "";
-        try {
-            HttpSession session = request.getSession(true);
-            Set<String> userApps = (Set<String>) session.getAttribute("authComponents");
-            if (userApps == null) {
-                userApps = new TreeSet<String>();
-            }
-            outboundJson = mapper.writeValueAsString(userApps);
-        } catch (Exception ex) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "DashboardHomeController");
-            MDC.put("TargetServiceName", "DashboardHomeController");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Get User Apps failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "Failed to get apps list");
-            RestResponseError response = new RestResponseError("Failed to get apps list", ex);
-            outboundJson = response.toJson();
-        } finally {
-            postLogAudit(request);
-        }
-        return outboundJson;
-    }
-
-    /**
-     * Sets the controller endpoint selection for the user.
-     *
-     * @param request HttpServletRequest
-     * @param endpoint Body with endpoint details
-     * @return Result indicating success or failure
-     * @throws Exception if application user is not found
-     */
-    @RequestMapping(
-        value = {COMPONENTS_PATH},
-        method = RequestMethod.POST,
-        produces = "application/json")
-    @ResponseBody
-    public String insertComponent(HttpServletRequest request,
-        @RequestBody EcdComponent newComponent) throws Exception {
-        preLogAudit(request);
-        String outboundJson = null;
-        controllerEndpointService.insertComponent(newComponent);
-        RestResponseSuccess success =
-            new RestResponseSuccess("Inserted new component with name " + newComponent.getCname());
-        outboundJson = mapper.writeValueAsString(success);
-        postLogAudit(request);
-        return outboundJson;
-    }
-
+    
     public void preLogAudit(HttpServletRequest request) {
         begin = new Date();
         MDC.put(SystemProperties.AUDITLOG_BEGIN_TIMESTAMP, logDateFormat.format(begin));
index f3b6147..cc1e9d8 100644 (file)
@@ -27,7 +27,6 @@ import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
 
-import org.onap.ccsdk.dashboard.service.ControllerEndpointService;
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
 import org.onap.portalsdk.core.controller.RestrictedBaseController;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -72,12 +71,7 @@ public class DashboardRestrictedBaseController extends RestrictedBaseController
     @Autowired
     protected DashboardProperties appProperties;
 
-    /**
-     * For getting selected controller
-     */
-    @Autowired
-    private ControllerEndpointService controllerEndpointService;
-
     /**
      * Hello Spring, here's your no-arg constructor.
      */
index 0346ad7..d98c404 100644 (file)
@@ -22,7 +22,6 @@
 package org.onap.ccsdk.dashboard.controller;
 
 import java.util.Date;
-
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -50,8 +49,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
-
 /**
  * Controller for Deployment Handler features: get/put/delete deployments
  * Methods serve Ajax requests made by Angular scripts on pages that show
@@ -63,14 +60,15 @@ public class DeploymentHandlerController extends DashboardRestrictedBaseControll
 
     private static EELFLoggerDelegate logger =
         EELFLoggerDelegate.getLogger(DeploymentHandlerController.class);
-
+    
     @Autowired
     DeploymentHandlerClient deploymentHandlerClient;
-
+    
     private static final String DEPLOYMENTS_PATH = "dcae-deployments";
 
     private static Date begin, end;
 
+    @SuppressWarnings("unchecked")
     @RequestMapping(value = {
             DEPLOYMENTS_PATH + "/{deploymentId:.+}" }, method = RequestMethod.PUT, produces = "application/json")
     @ResponseBody
@@ -83,13 +81,8 @@ public class DeploymentHandlerController extends DashboardRestrictedBaseControll
                 json = objectMapper.writeValueAsString(deploymentHandlerClient.putDeployment(
                         deploymentRequestObject.getDeploymentId(), deploymentRequestObject.getTenant(),
                         new DeploymentRequest(deploymentRequestObject.getServiceTypeId(),
-                                deploymentRequestObject.getInputs())));
-            } else {
-                json = objectMapper.writeValueAsString(deploymentHandlerClient.updateDeployment(
-                        deploymentRequestObject.getDeploymentId(), deploymentRequestObject.getTenant(),
-                        new DeploymentRequest(deploymentRequestObject.getServiceTypeId(),
-                                deploymentRequestObject.getInputs())));
-            }
+                                deploymentRequestObject.getInputs()), request));                 
+            } 
         } catch (BadRequestException e) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "Deployment Handler");
@@ -151,9 +144,7 @@ public class DeploymentHandlerController extends DashboardRestrictedBaseControll
         String json = null;
         StringBuffer status = new StringBuffer();
         try {
-            // DeploymentHandlerClient deploymentHandlerClient =
-            // getDeploymentHandlerClient(request);
-            deploymentHandlerClient.deleteDeployment(deploymentId, tenant);
+            deploymentHandlerClient.deleteDeployment(deploymentId, tenant, request);
             String self = request.getRequestURL().toString().split("\\?")[0];
             status.append(self).append("/executions?tenant=").append(tenant);
             DeploymentResource deplRsrc = new DeploymentResource(deploymentId,
index 49d5709..ad671ad 100644 (file)
@@ -26,8 +26,6 @@ package org.onap.ccsdk.dashboard.controller;
  * ECOMP Portal SDK
  * ================================================================================
  * Copyright (C) 2017 AT&T Intellectual Property
- * 
- * Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -47,6 +45,7 @@ import java.net.URLDecoder;
 import java.net.URLEncoder;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.TreeSet;
 
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
@@ -56,12 +55,16 @@ import javax.servlet.http.HttpSession;
 import org.onap.portalsdk.core.auth.LoginStrategy;
 import org.onap.portalsdk.core.command.LoginBean;
 import org.onap.portalsdk.core.controller.UnRestrictedBaseController;
+import org.onap.portalsdk.core.domain.Role;
 import org.onap.portalsdk.core.domain.User;
+import org.onap.portalsdk.core.domain.UserApp;
+import org.onap.portalsdk.core.domain.FusionObject.Parameters;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.onap.portalsdk.core.menu.MenuProperties;
 import org.onap.portalsdk.core.onboarding.listener.PortalTimeoutHandler;
 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
 import org.onap.portalsdk.core.onboarding.util.PortalApiProperties;
+import org.onap.portalsdk.core.service.DataAccessService;
 import org.onap.portalsdk.core.service.LoginService;
 import org.onap.portalsdk.core.service.RoleService;
 import org.onap.portalsdk.core.util.SystemProperties;
@@ -98,9 +101,84 @@ public class ECDSingleSignOnController extends UnRestrictedBaseController {
     @Autowired
     private RoleService roleService;
 
+    @Autowired
+    private DataAccessService dataAccessService;
+    
     private String viewName;
     private String welcomeView;
 
+    @RequestMapping(value = { "signup.htm" }, method = RequestMethod.GET)
+    public ModelAndView externalLogin() {
+        Map<String, Object> model = new HashMap<>();
+        return new ModelAndView("signup", "model", model);
+    }
+    
+    /**
+     * User sign up handler 
+     * 
+     * @param request
+     * @return
+     * @throws Exception 
+     */
+    @RequestMapping(value = { "/signup" }, method = RequestMethod.POST)
+    public ModelAndView userSignup(HttpServletRequest request, HttpServletResponse response) throws Exception {
+        LoginBean commandBean = new LoginBean();
+        String loginId = request.getParameter("loginId");
+        String password = request.getParameter("password");
+        if (loginId.isEmpty() || password.isEmpty()) {
+            String loginErrorMessage = "User name and/or password missing";
+            Map<String, String> model = new HashMap<>();
+            model.put("error", loginErrorMessage);
+            return new ModelAndView("signup", "model", model);
+        }   
+        commandBean.setLoginId(loginId);
+        commandBean.setLoginPwd(password);
+        commandBean.setUserid(loginId);
+        commandBean = loginService.findUser(commandBean,
+                (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY), new HashMap());
+
+        if (commandBean.getUser() == null) {
+            // add new user                                  
+            User user = new User();
+            user.setLoginId(loginId);
+            user.setLoginPwd(password);
+            user.setActive(true);
+            user.setOrgUserId(loginId);
+            user.setLastName(request.getParameter("last"));
+            user.setFirstName(request.getParameter("first"));
+            user.setEmail(request.getParameter("email"));
+            Role role = null;
+            HashMap additionalParams = new HashMap();
+            additionalParams.put(Parameters.PARAM_HTTP_REQUEST, request);
+            user.setRoles(new TreeSet<Role>());
+            user.setUserApps(new TreeSet<UserApp>());
+            user.setPseudoRoles(new TreeSet<Role>());
+            try {
+                dataAccessService.saveDomainObject(user, additionalParams);
+                 role = (Role) dataAccessService.getDomainObject(Role.class,
+                        Long.valueOf(SystemProperties.getProperty(SystemProperties.POST_DEFAULT_ROLE_ID)),
+                        null);
+                 if(role.getId() == null){
+                        logger.error(EELFLoggerDelegate.errorLogger,
+                                "process failed: No Role Exsists in DB with requested RoleId :"+ Long.valueOf(SystemProperties.getProperty(SystemProperties.POST_DEFAULT_ROLE_ID)));
+                        throw new Exception("user cannot be added");
+                }
+                user.addRole(role);
+                //saveUserExtension(user);
+                dataAccessService.saveDomainObject(user, additionalParams);
+                } catch (Exception e) {
+                     logger.error(EELFLoggerDelegate.errorLogger, "saveDomainObject failed on user " + user.getLoginId(), e);
+                     String loginErrorMessage = (e.getMessage() != null) ? e.getMessage()
+                         : "login.error.external.invalid - saveDomainObject failed on user " + user.getLoginId();
+                     Map<String, String> model = new HashMap<>();
+                     model.put("error", loginErrorMessage);
+                     return new ModelAndView("signup", "model", model);
+            }
+        }
+        Map<String, Object> model = new HashMap<>();
+        return new ModelAndView("login_external", "model", model);
+    }
+    
     /**
      * Handles requests directed to the single sign-on page by the session timeout
      * interceptor.
@@ -225,6 +303,16 @@ public class ECDSingleSignOnController extends UnRestrictedBaseController {
         }
     }
 
+    @RequestMapping(value = { "logout.htm" }, method = RequestMethod.GET)
+    public ModelAndView appLogout(HttpServletRequest request) {
+        try {
+            request.getSession().invalidate();
+        } catch (Exception e) {
+            logger.error(EELFLoggerDelegate.errorLogger, "Logout failed", e);
+        }
+        return new ModelAndView("redirect:login.htm");
+    }
+
     /**
      * Discover if the portal is available by GET-ing a resource from the REST URL
      * specified in portal.properties, using a very short timeout.
@@ -273,16 +361,14 @@ public class ECDSingleSignOnController extends UnRestrictedBaseController {
         return request.getSession().getId();
     }
 
-    @Override
     public String getViewName() {
         return viewName;
     }
-    
-    @Override
+
     public void setViewName(String viewName) {
         this.viewName = viewName;
     }
-    
+
     public String getWelcomeView() {
         return welcomeView;
     }
index 5087ad1..f8fd19e 100644 (file)
@@ -2,22 +2,22 @@
  * =============LICENSE_START=========================================================
  *
  * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
- *  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.
+ * 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.
  * ============LICENSE_END=========================================================
  *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
 
 package org.onap.ccsdk.dashboard.controller;
@@ -25,30 +25,48 @@ package org.onap.ccsdk.dashboard.controller;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.http.HttpStatus;
 import org.onap.ccsdk.dashboard.model.HealthStatus;
+import org.onap.ccsdk.dashboard.rest.CloudifyClient;
+import org.onap.ccsdk.dashboard.rest.DeploymentHandlerClient;
+import org.onap.ccsdk.dashboard.rest.InventoryClient;
+import org.onap.portalsdk.core.controller.FusionBaseController;
 import org.onap.portalsdk.core.util.SystemProperties;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+
 /**
  * This controller responds to probes for application health, returning a JSON
  * body to indicate current status.
  */
 @RestController
-@Configuration
-@EnableAspectJAutoProxy
 @RequestMapping("/")
-public class HealthCheckController extends DashboardRestrictedBaseController {
+public class HealthCheckController extends FusionBaseController {
 
+    @Autowired
+    InventoryClient inventoryClient;
+    
+    @Autowired
+    DeploymentHandlerClient deploymentHandlerClient;
+    
+    @Autowired
+    CloudifyClient cfyClient;
+    
     /**
      * Application name
      */
     protected static final String APP_NAME = "ecd-app";
 
     private static final String APP_HEALTH_CHECK_PATH = "/health";
+    private static final String APP_SRVC_HEALTH_CHECK_PATH = "/health-info";
+
+    protected final ObjectMapper objectMapper = new ObjectMapper();
 
     /**
      * application health by simply responding with a JSON object indicating status
@@ -56,9 +74,13 @@ public class HealthCheckController extends DashboardRestrictedBaseController {
      * @param request HttpServletRequest
      * @return HealthStatus object always
      */
-    @RequestMapping(value = { APP_HEALTH_CHECK_PATH }, method = RequestMethod.GET, produces = "application/json")
+    @RequestMapping(
+        value = {APP_HEALTH_CHECK_PATH},
+        method = RequestMethod.GET,
+        produces = "application/json")
     public HealthStatus healthCheck(HttpServletRequest request, HttpServletResponse response) {
         return new HealthStatus(200, SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME)
             + " health check passed ");
     }
+
 }
index 4251212..3877dfc 100644 (file)
 
 package org.onap.ccsdk.dashboard.controller;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.function.Predicate;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
+import org.apache.http.HttpStatus;
 import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException;
-import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceAlreadyDeactivatedException;
-import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceNotFoundException;
 import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeAlreadyDeactivatedException;
 import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException;
 import org.onap.ccsdk.dashboard.model.RestResponseError;
 import org.onap.ccsdk.dashboard.model.RestResponsePage;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant;
+import org.onap.ccsdk.dashboard.model.cloudify.ServiceRefCfyList;
 import org.onap.ccsdk.dashboard.model.inventory.Blueprint;
-import org.onap.ccsdk.dashboard.model.inventory.Service;
+import org.onap.ccsdk.dashboard.model.inventory.BlueprintResponse;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceRef;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceType;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeServiceMap;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary;
+import org.onap.ccsdk.dashboard.rest.CloudifyClient;
+import org.onap.ccsdk.dashboard.rest.ConsulClient;
 import org.onap.ccsdk.dashboard.rest.InventoryClient;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.onap.portalsdk.core.objectcache.AbstractCacheManager;
 import org.onap.portalsdk.core.util.SystemProperties;
 import org.onap.portalsdk.core.web.support.AppUtils;
-import org.onap.ccsdk.dashboard.util.DashboardProperties;
-
+import org.onap.portalsdk.core.web.support.UserUtils;
 import org.slf4j.MDC;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -84,105 +95,40 @@ public class InventoryController extends DashboardRestrictedBaseController {
 
     @Autowired
     InventoryClient inventoryClient;
+    @Autowired
+    CloudifyClient cloudifyClient;
+    @Autowired
+    ConsulClient consulClient;
+    
+    /**
+     * For caching data 
+     */
+    private AbstractCacheManager cacheManager;
+    
 
+    @Autowired
+    public void setCacheManager(AbstractCacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+    }
+
+    public AbstractCacheManager getCacheManager() {
+        return cacheManager;
+    }
+    
     /**
      * Enum for selecting an item type.
      */
     public enum InventoryDataItem {
-        SERVICES, SERVICE_TYPES, SERVICES_GROUPBY;
+        SERVICE_TYPES, SERVICE_TYPE_NAME, OWNER, SERVICE_TYPE_ID;
     }
 
     private static Date begin, end;
-    private static final String SERVICES_PATH = "dcae-services";
+    private static final String OWNERS = "owners";
     private static final String SERVICE_TYPES_PATH = "dcae-service-types";
+    private static final String SERVICE_TYPE_NAME = "service-type-list";
     private static final String VIEW_SERVICE_TYPE_BLUEPRINT_PATH = "dcae-service-type-blueprint";
     private static final String DEP_IDS_FOR_TYPE = "dcae-services/typeIds";
-
-    /**
-     * Gets one page of objects and supporting information via the REST client. On
-     * success, returns a PaginatedRestResponse object as String.
-     * 
-     * @param option Specifies which item list type to get
-     * @param pageNum Page number of results
-     * @param pageSize Number of items per browser page
-     * @return JSON block as String, see above.
-     * @throws Exception On any error; e.g., Network failure.
-     */
-    @SuppressWarnings({"rawtypes", "unchecked"})
-    private String getItemListForPage(HttpServletRequest request, InventoryDataItem option,
-        int pageNum, int pageSize, String sortBy, String searchBy) throws Exception {
-        List itemList = null;
-        switch (option) {
-            case SERVICES:
-                itemList = inventoryClient.getServices().collect(Collectors.toList());
-                if (searchBy != null) {
-                    itemList = (List) itemList.stream()
-                        .filter(s -> ((Service) s).contains(searchBy)).collect(Collectors.toList());
-                }
-                for (Service bp : (List<Service>) itemList) {
-                    bp.setCanDeploy(Optional.of(true));
-                }
-                if (sortBy != null) {
-                    if (sortBy.equals("deploymentRef")) {
-                        Collections.sort(itemList, serviceDeploymentRefComparator);
-                    } else if (sortBy.equals("serviceId")) {
-                        Collections.sort(itemList, serviceIdComparator);
-                    } else if (sortBy.equals("created")) {
-                        Collections.sort(itemList, serviceCreatedComparator);
-                    } else if (sortBy.equals("modified")) {
-                        Collections.sort(itemList, serviceModifiedComparator);
-                    }
-                }
-                break;
-            case SERVICE_TYPES:
-                itemList = inventoryClient.getServiceTypes().collect(Collectors.toList());
-                if (searchBy != null) {
-                    itemList =
-                        (List) itemList.stream().filter(s -> ((ServiceType) s).contains(searchBy))
-                            .collect(Collectors.toList());
-                }
-                for (ServiceType bp : (List<ServiceType>) itemList) {
-                    bp.setCanDeploy(Optional.of(true));
-                }
-                if (sortBy != null) {
-                    if (sortBy.equals("owner")) {
-                        Collections.sort(itemList, serviceTypeOwnerComparator);
-                    } else if (sortBy.equals("typeId")) {
-                        Collections.sort(itemList, serviceTypeIdComparator);
-                    } else if (sortBy.equals("typeName")) {
-                        Collections.sort(itemList, serviceTypeNameComparator);
-                    } else if (sortBy.equals("typeVersion")) {
-                        Collections.sort(itemList, serviceTypeVersionComparator);
-                    } else if (sortBy.equals("created")) {
-                        Collections.sort(itemList, serviceTypeCreatedComparator);
-                    } else if (sortBy.equals("application")) {
-                        Collections.sort(itemList, serviceTypeApplComparator);
-                    } else if (sortBy.equals("component")) {
-                        Collections.sort(itemList, serviceTypeCompComparator);
-                    }
-                }
-                break;
-            default:
-                MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-                MDC.put("TargetEntity", "DCAE Inventory");
-                MDC.put("TargetServiceName", "DCAE Inventory");
-                MDC.put("ErrorCode", "300");
-                MDC.put("ErrorCategory", "ERROR");
-                MDC.put("ErrorDescription", "Getting page of items failed!");
-                throw new Exception(
-                    "getItemListForPage failed: unimplemented case: " + option.name());
-        }
-
-        // Shrink if needed
-        final int totalItems = itemList.size();
-        final int pageCount = (int) Math.ceil((double) totalItems / pageSize);
-        if (totalItems > pageSize)
-            itemList = getPageOfList(pageNum, pageSize, itemList);
-
-        RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList);
-        String outboundJson = objectMapper.writeValueAsString(model);
-        return outboundJson;
-    }
+    private static final String SERVICE_TYPE_ID = "service-type-id-list";
 
     /**
      * version with user role auth Gets one page of objects and supporting
@@ -202,171 +148,211 @@ public class InventoryController extends DashboardRestrictedBaseController {
         HashMap<String, Boolean> comp_deploy_tab =
             (HashMap<String, Boolean>) session.getAttribute("comp_access");
         String roleLevel = (String) session.getAttribute("role_level");
-
+        String roleAuth = (String) session.getAttribute("auth_role");
+        String user = UserUtils.getUserSession(request).getLoginId();
+        
         if (roleLevel == null) {
             roleLevel = "dev";
         }
         if (comp_deploy_tab == null) {
             comp_deploy_tab = new HashMap<String, Boolean>();
         }
-
+        if (roleAuth == null) {
+            roleAuth = "READ";
+        }
         Set<String> userApps = (Set<String>) session.getAttribute("authComponents");
         if (userApps == null) {
             userApps = new TreeSet<String>();
         }
-
+        ReadWriteLock lock = new ReentrantReadWriteLock();
         List itemList = null;
-        List<ServiceType> filterList = new ArrayList<ServiceType>();
-        List<Service> authDepList = new ArrayList<Service>();
-        switch (option) {
-            case SERVICES:
-                itemList = inventoryClient.getServices().collect(Collectors.toList());
-                if (roleLevel.equals("app")) {
-                    for (String userRole : userApps) {
-                        logger.debug(">>>> check component type from deployment: " + userRole);
-                        for (Service cont : (List<Service>) itemList) {
-                            String deplRef = cont.getDeploymentRef().toLowerCase();
-                            logger.debug(">>>> container deployment name: " + deplRef);
-                            if (deplRef.contains(userRole)) {
-                                logger.debug(">>>> adding deployment item to filtered subset");
-                                authDepList.add(cont);
-                            }
-                        }
-                    }
-                }
+        List bpItemList = null;
+        int totalItems = 0;
+
+        lock.readLock().lock();
+        List<ServiceTypeSummary> bpList = 
+            (List<ServiceTypeSummary>)getCacheManager().getObject(SERVICE_TYPES_PATH);
+        lock.readLock().unlock();
+        if (bpList == null) {
+            bpList = inventoryClient.getServiceTypes().collect(Collectors.toList());
+        }
 
-                if (searchBy != null) {
-                    if (!roleLevel.equals("app")) {
-                        itemList =
-                            (List) itemList.stream().filter(s -> ((Service) s).contains(searchBy))
-                                .collect(Collectors.toList());
-                    } else {
-                        if (!authDepList.isEmpty()) {
-                            authDepList = (List) authDepList.stream()
-                                .filter(s -> ((Service) s).contains(searchBy))
-                                .collect(Collectors.toList());
-                        }
-                    }
+        String svcRefFilterStr = "";
+        String appFilterStr = "";
+        String compFilterStr = "";
+        String ownerFilterStr = "";
+        String containsFilterStr = "";
+        // apply user search filters
+        if (searchBy != null && !searchBy.isEmpty()) {
+            // parse the search filters string 
+            // look for service name patterns           
+            List<String> searchFilters = 
+                new ArrayList<String>(Arrays.asList(searchBy.split(";")));
+            if (searchFilters.stream().anyMatch(s->s.startsWith("contains"))) {
+                List<String> containsList = searchFilters.stream().filter(s->s.startsWith("contains")).
+                    collect(Collectors.toList());
+                containsFilterStr = containsList.get(0).split(":")[1];
+            }
+            if (searchFilters.stream().anyMatch(s->s.startsWith("serviceRef"))) {
+                List<String> svcRefsList = searchFilters.stream().filter(s->s.startsWith("serviceRef")).
+                    collect(Collectors.toList());
+                svcRefFilterStr = svcRefsList.get(0).split(":")[1];
+            }
+            if (searchFilters.stream().anyMatch(s->s.startsWith("app"))) {
+                List<String> appsList = searchFilters.stream().filter(s->s.startsWith("app")).
+                    collect(Collectors.toList());
+                appFilterStr = appsList.get(0).split(":")[1];
+            }
+            if (searchFilters.stream().anyMatch(s->s.startsWith("comp"))) {
+                List<String> compList = searchFilters.stream().filter(s->s.startsWith("comp")).
+                    collect(Collectors.toList());
+                compFilterStr = compList.get(0).split(":")[1];
+            }
+            if (searchFilters.stream().anyMatch(s->s.startsWith("owner"))) {
+                List<String> ownerList = searchFilters.stream().filter(s->s.startsWith("owner")).
+                    collect(Collectors.toList());
+                ownerFilterStr = ownerList.get(0).split(":")[1];
+            }
+            if (!ownerFilterStr.isEmpty()) {
+                List<ServiceTypeSummary> ownerBpList = new ArrayList<ServiceTypeSummary>();
+                lock.readLock().lock();                     
+                Map<String, List<ServiceTypeSummary>> bpPerOwner =
+                    (Map<String, List<ServiceTypeSummary>>) getCacheManager().getObject("owner_bp_map");
+                lock.readLock().unlock();
+
+                List<String> ownerFilterList = 
+                    new ArrayList<String>(Arrays.asList(ownerFilterStr.split(","))); 
+                
+                if (ownerFilterList.size() == 1 && ownerFilterList.get(0).equals("undefined")) {
+                    ownerFilterList.clear();
+                    ownerFilterList.add(user);
                 }
-                if (roleLevel.equals("app")) {
-                    logger.debug(">>>> update response with authorized content");
-                    itemList.clear();
-                    itemList.addAll(authDepList);
+                
+                if (bpPerOwner != null) {
+                    Stream<Map.Entry<String, List<ServiceTypeSummary>>> bpOwnerEntriesStream = 
+                        bpPerOwner.entrySet().stream(); 
+
+                    Set<Map.Entry<String, List<ServiceTypeSummary>>> bpOwnerSet = 
+                        bpOwnerEntriesStream.filter(m -> ownerFilterList.stream().
+                        anyMatch(ownFilter -> m.getKey().equalsIgnoreCase(ownFilter))).collect(Collectors.toSet());
+                    bpOwnerSet.stream().forEach(e -> ownerBpList.addAll(e.getValue()));
+                    bpItemList = ownerBpList;
                 }
-
-                // check for authorization to perform delete deployed blueprints
-
-                if (!roleLevel.equals("ops")) {
-                    for (Service bp : (List<Service>) itemList) {
-                        String deplRef = bp.getDeploymentRef().split("_")[0].toLowerCase();
-                        logger.debug(">>>> deployment reference: " + deplRef);
-                        if (comp_deploy_tab.containsKey(deplRef)) {
-                            boolean enableDeploy = comp_deploy_tab.get(deplRef);
-                            logger.debug(">>>> enable deploy button: " + enableDeploy);
-                            bp.setCanDeploy(Optional.of(enableDeploy));
-                        } else {
-                            bp.setCanDeploy(Optional.of(false));
-                        }
-                    }
-                } else {
-                    for (Service bp : (List<Service>) itemList) {
-                        bp.setCanDeploy(Optional.of(true));
-                    }
-                }
-
-                if (sortBy != null) {
-                    if (sortBy.equals("deploymentRef")) {
-                        Collections.sort(itemList, serviceDeploymentRefComparator);
-                    } else if (sortBy.equals("serviceId")) {
-                        Collections.sort(itemList, serviceIdComparator);
-                    } else if (sortBy.equals("created")) {
-                        Collections.sort(itemList, serviceCreatedComparator);
-                    } else if (sortBy.equals("modified")) {
-                        Collections.sort(itemList, serviceModifiedComparator);
-                    }
+                if (bpItemList == null) {
+                    bpItemList = new ArrayList<ServiceTypeSummary>();
+                    bpItemList.addAll(bpList);
                 }
+            }
+        }
+        if (bpItemList == null) {
+            bpItemList = new ArrayList<ServiceTypeSummary>();
+            bpItemList.addAll(bpList);
+        }
+        // apply role based filtering
+        if (roleLevel.equals("app")) {
+            @SuppressWarnings("unchecked")
+            List<String> myApps = new ArrayList(userApps);
+            bpItemList = (List<ServiceTypeSummary>)bpItemList.stream().filter(s -> myApps.stream()
+                .anyMatch(appFilter -> (((ServiceTypeSummary)s).getComponent() != null && 
+                    ((ServiceTypeSummary)s).getComponent().equalsIgnoreCase(appFilter))))
+                .collect(Collectors.<ServiceTypeSummary>toList());                           
+        } else if (roleLevel.equals("app_dev")) {
+            Predicate<ServiceTypeSummary> appFilter =
+                p -> p.getComponent() != null && !p.getComponent().equalsIgnoreCase("dcae") 
+                    && !p.getComponent().equalsIgnoreCase("d2a");
+                bpItemList = (List<ServiceTypeSummary>)bpItemList.stream().filter(appFilter).
+                    collect(Collectors.toList());
+        } 
+        
+        switch (option) {
+            case OWNER:
+                Set<String> ownersList = 
+                    (Set) bpItemList.stream().map(x -> ((ServiceTypeSummary)x).getOwner()).collect(Collectors.toSet());              
+                return objectMapper.writeValueAsString(ownersList);
+            case SERVICE_TYPE_ID:
+                itemList = bpItemList;
+                totalItems = itemList.size();
+                RestResponsePage<List> model = new RestResponsePage<>(totalItems, 1, itemList);
+                String outboundJson = objectMapper.writeValueAsString(model);
+                return outboundJson;                            
+            case SERVICE_TYPE_NAME:        
+                Set<String> svcTypeList = 
+                    (Set) bpItemList.stream().map(x -> ((ServiceTypeSummary)x).getTypeName()).collect(Collectors.toSet());
+                itemList = new ArrayList<String>();
+                itemList.addAll(svcTypeList);
                 break;
             case SERVICE_TYPES:
-                ServiceTypeQueryParams serviceQueryParams =
-                    new ServiceTypeQueryParams.Builder().onlyLatest(false).build();
-                itemList = inventoryClient.getServiceTypes(serviceQueryParams)
-                    .collect(Collectors.toList());
-                if (roleLevel.equals("app")) {
-                    for (String userApp : userApps) {
-                        logger.debug(">>>> check component type from BP: " + userApp);
-                        for (ServiceType bp : (List<ServiceType>) itemList) {
-                            String bpComp = bp.getComponent();
-                            String bpOwner = bp.getOwner(); // for backward compatibility
-                            logger.debug(">>>> BP component name: " + bpComp);
-                            if ((bpComp != null && bpComp.equalsIgnoreCase(userApp))
-                                || bpOwner.contains(userApp)) {
-                                logger.debug(">>>> adding item to filtered subset");
-                                filterList.add(bp);
-                            }
-                        }
-                    }
+                // apply response filters
+                itemList = bpItemList;
+                String outFilter = request.getParameter("_include");
+                if (outFilter != null) {
+                    List<String> svcSummaryList = 
+                        (List) itemList.stream().map(x -> extractBpSummary((ServiceTypeSummary)x)).collect(Collectors.toList());
+                    return objectMapper.writeValueAsString(svcSummaryList);
                 }
-                if (searchBy != null) {
-                    if (!roleLevel.equals("app")) {
-                        itemList = (List) itemList.stream()
-                            .filter(s -> ((ServiceType) s).contains(searchBy))
-                            .collect(Collectors.toList());
-                    } else {
-                        if (!filterList.isEmpty()) {
-                            filterList = (List) filterList.stream()
-                                .filter(s -> ((ServiceType) s).contains(searchBy))
+                // apply user search filters
+                if (searchBy != null && !searchBy.isEmpty()) {
+                    if (!svcRefFilterStr.isEmpty()) {
+                        List<String> svcFilterList = 
+                            new ArrayList<String>(Arrays.asList(svcRefFilterStr.split(",")));
+                        if (!svcFilterList.isEmpty()) {
+                            itemList =  (List) itemList.stream().filter(s -> svcFilterList.stream()
+                                .anyMatch(svcFilter -> ((ServiceTypeSummary) s).getTypeName().toLowerCase().contains(svcFilter.toLowerCase())))
                                 .collect(Collectors.toList());
                         }
+                    }                                      
+                    if (!appFilterStr.isEmpty()) {
+                        List<String> appFilterList = 
+                            new ArrayList<String>(Arrays.asList(appFilterStr.split(",")));
+                        Predicate<ServiceTypeSummary> srvcAppFilter =
+                            p -> p.getApplication() != null;
+                            Stream<ServiceTypeSummary> svcStream = itemList.stream();
+
+                            itemList =  svcStream.filter( srvcAppFilter.and(
+                                s -> appFilterList.stream()
+                                .anyMatch(appFilter ->((ServiceTypeSummary) s).getApplication().equalsIgnoreCase(appFilter))))
+                                .collect(Collectors.toList()); 
+                    } 
+                    if (!compFilterStr.isEmpty()) {
+                        List<String> compFilterList = 
+                            new ArrayList<String>(Arrays.asList(compFilterStr.split(",")));                       
+                        Predicate<ServiceTypeSummary> srvcCompFilter =
+                            p -> p.getComponent() != null;
+                            Stream<ServiceTypeSummary> svcStream = itemList.stream();
+                            itemList =  svcStream.filter( srvcCompFilter.and(
+                                s -> compFilterList.stream()
+                                .anyMatch(compFilter ->((ServiceTypeSummary) s).getComponent().equalsIgnoreCase(compFilter))))
+                                .collect(Collectors.toList()); 
                     }
-                }
-                if (roleLevel.equals("app")) {
-                    logger.debug(">>>> update response with authorized content");
-                    itemList.clear();
-                    itemList.addAll(filterList);
-                }
 
-                // check for authorization to perform update/delete/deploy blueprints
-                if (!roleLevel.equals("ops")) {
-                    for (ServiceType bp : (List<ServiceType>) itemList) {
-                        String bpComp = bp.getComponent();
-                        if (bpComp != null && bpComp.length() > 0) {
-                            bpComp = bpComp.toLowerCase();
-                        } else {
-                            String bpOwner = bp.getOwner(); // for backward compatibility
-                            if (bpOwner != null && bpOwner.contains(":")) {
-                                bpComp = bp.getOwner().split(":")[0].toLowerCase();
-                            }
-                        }
-                        logger.debug(">>>> BP component name: " + bpComp);
-                        if (comp_deploy_tab.containsKey(bpComp)) {
-                            boolean enableDeploy = comp_deploy_tab.get(bpComp);
-                            logger.debug(">>>> enable deploy button: " + enableDeploy);
-                            bp.setCanDeploy(Optional.of(enableDeploy));
-                        } else {
-                            bp.setCanDeploy(Optional.of(false));
-                        }
+                    if (!containsFilterStr.isEmpty()) {
+                        final String simpleSrch = containsFilterStr.split(",")[0];
+                        itemList = (List<ServiceTypeSummary>) itemList.stream()
+                            .filter(s -> ((ServiceTypeSummary) s).contains(simpleSrch)).collect(Collectors.toList());
                     }
-                } else {
-                    for (ServiceType bp : (List<ServiceType>) itemList) {
-                        bp.setCanDeploy(Optional.of(true));
-                    }
-                }
-
+                } 
                 if (sortBy != null) {
                     if (sortBy.equals("owner")) {
-                        Collections.sort(itemList, serviceTypeOwnerComparator);
+                        ((List<ServiceTypeSummary>)itemList).sort(
+                            (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getOwner().compareTo(o2.getOwner()));
                     } else if (sortBy.equals("typeId")) {
-                        Collections.sort(itemList, serviceTypeIdComparator);
+                        ((List<ServiceTypeSummary>)itemList).sort(
+                            (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getTypeId().get().compareTo(o2.getTypeId().get()));
                     } else if (sortBy.equals("typeName")) {
-                        Collections.sort(itemList, serviceTypeNameComparator);
+                        ((List<ServiceTypeSummary>)itemList).sort(
+                            (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getTypeName().compareTo(o2.getTypeName()));
                     } else if (sortBy.equals("typeVersion")) {
-                        Collections.sort(itemList, serviceTypeVersionComparator);
+                        ((List<ServiceTypeSummary>)itemList).sort(
+                            (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getTypeVersion().compareTo(o2.getTypeVersion()));
                     } else if (sortBy.equals("created")) {
-                        Collections.sort(itemList, serviceTypeCreatedComparator);
+                        ((List<ServiceTypeSummary>)itemList).sort(
+                            (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getCreated().get().compareTo(o2.getCreated().get()));
                     } else if (sortBy.equals("application")) {
-                        Collections.sort(itemList, serviceTypeApplComparator);
+                        ((List<ServiceTypeSummary>)itemList).sort(
+                            (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getApplication().compareTo(o2.getApplication()));
                     } else if (sortBy.equals("component")) {
-                        Collections.sort(itemList, serviceTypeCompComparator);
+                        ((List<ServiceTypeSummary>)itemList).sort(
+                            (ServiceTypeSummary o1, ServiceTypeSummary o2) -> o1.getComponent().compareTo(o2.getComponent()));
                     }
                 }
                 break;
@@ -380,18 +366,91 @@ public class InventoryController extends DashboardRestrictedBaseController {
                 throw new Exception(
                     "getItemListForPage failed: unimplemented case: " + option.name());
         }
-
         // Shrink if needed
-        final int totalItems = itemList.size();
+        if (itemList != null) {
+            totalItems = itemList.size();
+        }
         final int pageCount = (int) Math.ceil((double) totalItems / pageSize);
-        if (totalItems > pageSize)
+        if (totalItems > pageSize && option.equals(InventoryDataItem.SERVICE_TYPES)) {
             itemList = getPageOfList(pageNum, pageSize, itemList);
-
+        }       
+        if (option.equals(InventoryDataItem.SERVICE_TYPES)) {
+            if (!roleLevel.equals("ops")) {
+                if (roleLevel.equals("dev") || roleLevel.equals("app_dev")) {
+                    boolean deployFlag = roleAuth.equals("WRITE") ? true : false;
+                    for (ServiceTypeSummary bp : (List<ServiceTypeSummary>) itemList) {
+                        bp.setCanDeploy(Optional.of(deployFlag));
+                    }
+                } else {
+                    for (ServiceTypeSummary bp : (List<ServiceTypeSummary>) itemList) {
+                        String bpComp = bp.getComponent();
+                        if (bpComp != null && bpComp.length() > 0) {
+                            bpComp = bpComp.toLowerCase();
+                        } else {
+                            String bpOwner = bp.getOwner(); // for backward compatibility
+                            if (bpOwner != null && bpOwner.contains(":")) {
+                                bpComp = bp.getOwner().split(":")[0].toLowerCase();
+                            }
+                        }
+                        if (comp_deploy_tab.containsKey(bpComp)) {
+                            boolean enableDeploy = comp_deploy_tab.get(bpComp);
+                            logger.debug(">>>> enable deploy button: " + enableDeploy);
+                            bp.setCanDeploy(Optional.of(enableDeploy));
+                        } else {
+                            bp.setCanDeploy(Optional.of(false));
+                        }
+                    }
+                }
+            } else {
+                for (ServiceTypeSummary bp : (List<ServiceTypeSummary>) itemList) {
+                    bp.setCanDeploy(Optional.of(true));
+                }
+            }
+            // add the deployments mapping to the list
+            lock.readLock().lock();
+            List<ServiceTypeServiceMap> cache_bp_map_arr = 
+                (List<ServiceTypeServiceMap>) getCacheManager().getObject("bp_deploy_map");
+            lock.readLock().unlock();
+            if (cache_bp_map_arr != null) {
+                for (ServiceTypeSummary bpSum: (List<ServiceTypeSummary>)itemList) {
+                    // correlate the cached data for deployments
+                        List<ServiceTypeServiceMap> bp_depl_list = 
+                            cache_bp_map_arr.stream().filter(
+                                (Predicate<? super ServiceTypeServiceMap>) 
+                                s->s.getServiceTypeId().equals(bpSum.getTypeId().get())).
+                                collect(Collectors.toList());
+                        if (bp_depl_list != null && !bp_depl_list.isEmpty()) {
+                            bpSum.setDeployments((ServiceRefCfyList)bp_depl_list.get(0).getServiceRefList());
+                        }
+                }
+            }
+        }
         RestResponsePage<List> model = new RestResponsePage<>(totalItems, pageCount, itemList);
         String outboundJson = objectMapper.writeValueAsString(model);
         return outboundJson;
     }
-
+    @SuppressWarnings("unchecked")
+    @Scheduled(fixedDelay=600000, initialDelay=150000)
+    public void cacheOwnerToBpMap() {
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        lock.readLock().lock();
+        List<ServiceTypeSummary> bpList = 
+            (List<ServiceTypeSummary>)getCacheManager().getObject(SERVICE_TYPES_PATH);
+        lock.readLock().unlock();
+        if (bpList != null) {
+            Map<String, List<ServiceTypeSummary>> bpPerOwner = bpList.stream()
+                .collect(Collectors.groupingBy(bp -> bp.getOwner()));
+    
+            lock.writeLock().lock();
+            getCacheManager().putObject("owner_bp_map", bpPerOwner);
+            lock.writeLock().unlock();
+        }
+    }
+    
+    private BlueprintResponse extractBpSummary(ServiceTypeSummary bp) {
+        return new BlueprintResponse(bp.getTypeName(), bp.getTypeVersion(), bp.getTypeId().get());
+    }
     /**
      * Gets one page of the specified items. This method traps exceptions and
      * constructs an appropriate JSON block to report errors.
@@ -407,16 +466,8 @@ public class InventoryController extends DashboardRestrictedBaseController {
         try {
             int pageNum = getRequestPageNumber(request);
             int pageSize = getRequestPageSize(request);
-            String appEnv = "os";
-            appEnv =
-                DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth");
-            if (appEnv.equals("os")) {
-                outboundJson =
-                    getItemListForPage(request, option, pageNum, pageSize, sortBy, searchBy);
-            } else {
-                outboundJson =
-                    getItemListForPageAuth(request, option, pageNum, pageSize, sortBy, searchBy);
-            }
+            outboundJson =
+                getItemListForPageAuth(request, option, pageNum, pageSize, sortBy, searchBy);
         } catch (Exception ex) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "DCAE Inventory");
@@ -445,121 +496,24 @@ public class InventoryController extends DashboardRestrictedBaseController {
     }
 
     /**
-     * Supports sorting service types by owner
-     */
-    private static Comparator<ServiceType> serviceTypeOwnerComparator =
-        new Comparator<ServiceType>() {
-            @Override
-            public int compare(ServiceType o1, ServiceType o2) {
-                return o1.getOwner().compareToIgnoreCase(o2.getOwner());
-            }
-        };
-
-    /**
-     * Supports sorting service types by application
-     */
-    private static Comparator<ServiceType> serviceTypeApplComparator =
-        new Comparator<ServiceType>() {
-            @Override
-            public int compare(ServiceType o1, ServiceType o2) {
-                return o1.getApplication().compareToIgnoreCase(o2.getApplication());
-            }
-        };
-
-    /**
-     * Supports sorting service types by component
-     */
-    private static Comparator<ServiceType> serviceTypeCompComparator =
-        new Comparator<ServiceType>() {
-            @Override
-            public int compare(ServiceType o1, ServiceType o2) {
-                return o1.getComponent().compareToIgnoreCase(o2.getComponent());
-            }
-        };
-
-    /**
-     * Supports sorting service types by type id
-     */
-    private static Comparator<ServiceType> serviceTypeIdComparator = new Comparator<ServiceType>() {
-        @Override
-        public int compare(ServiceType o1, ServiceType o2) {
-            return o1.getTypeId().get().compareToIgnoreCase(o2.getTypeId().get());
-        }
-    };
-
-    /**
-     * Supports sorting service types by type name
-     */
-    private static Comparator<ServiceType> serviceTypeNameComparator =
-        new Comparator<ServiceType>() {
-            @Override
-            public int compare(ServiceType o1, ServiceType o2) {
-                return o1.getTypeName().compareToIgnoreCase(o2.getTypeName());
-            }
-        };
-
-    /**
-     * Supports sorting service types by type version
-     */
-    private static Comparator<ServiceType> serviceTypeVersionComparator =
-        new Comparator<ServiceType>() {
-            @Override
-            public int compare(ServiceType o1, ServiceType o2) {
-                return o1.getTypeVersion().compareTo(o2.getTypeVersion());
-            }
-        };
-
-    /**
-     * Supports sorting service types by created date
-     */
-    private static Comparator<ServiceType> serviceTypeCreatedComparator =
-        new Comparator<ServiceType>() {
-            @Override
-            public int compare(ServiceType o1, ServiceType o2) {
-                return o1.getCreated().get().compareToIgnoreCase(o2.getCreated().get());
-            }
-        };
-
-    /**
-     * Supports sorting services by deploymentRef
-     */
-    private static Comparator<Service> serviceDeploymentRefComparator = new Comparator<Service>() {
-        @Override
-        public int compare(Service o1, Service o2) {
-            return o1.getDeploymentRef().compareToIgnoreCase(o2.getDeploymentRef());
-        }
-    };
-
-    /**
-     * Supports sorting services by service id
-     */
-    private static Comparator<Service> serviceIdComparator = new Comparator<Service>() {
-        @Override
-        public int compare(Service o1, Service o2) {
-            return o1.getServiceId().compareToIgnoreCase(o2.getServiceId());
-        }
-    };
-
-    /**
-     * Supports sorting services by created date
-     */
-    private static Comparator<Service> serviceCreatedComparator = new Comparator<Service>() {
-        @Override
-        public int compare(Service o1, Service o2) {
-            return o1.getCreated().compareToIgnoreCase(o2.getCreated());
-        }
-    };
-
-    /**
-     * Supports sorting services by created date
+     * Serves one page of blueprint owners
+     * 
+     * @param request HttpServletRequest
+     * @return List of ServiceTypes objects
      */
-    private static Comparator<Service> serviceModifiedComparator = new Comparator<Service>() {
-        @Override
-        public int compare(Service o1, Service o2) {
-            return o1.getModified().compareToIgnoreCase(o2.getModified());
-        }
-    };
-
+    @RequestMapping(
+        value = {OWNERS},
+        method = RequestMethod.GET,
+        produces = "application/json")
+    @ResponseBody
+    public String getOwnersByPage(HttpServletRequest request) {
+        preLogAudit(request);
+        String json = getItemListForPageWrapper(request, InventoryDataItem.OWNER,
+            request.getParameter("sortBy"), request.getParameter("searchBy"));
+        postLogAudit(request);
+        return json;
+    }
+    
     /**
      * Serves one page of service types
      * 
@@ -600,27 +554,50 @@ public class InventoryController extends DashboardRestrictedBaseController {
         return objectMapper.writeValueAsString(result);
     }
 
+    
     /**
-     * Serves one page of services
-     *
+     * Serves the complete list of service type names
+     * 
      * @param request HttpServletRequest
-     *
-     * @return List of Service objects
+     * 
+     * @return list of service type names
      */
     @RequestMapping(
-        value = {SERVICES_PATH},
+        value = {SERVICE_TYPE_NAME},
         method = RequestMethod.GET,
         produces = "application/json")
     @ResponseBody
-    public String getServicesByPage(HttpServletRequest request) {
+    @Cacheable
+    public String getAllServiceTypeNames(HttpServletRequest request) {
         // preLogAudit(request);
         String json = null;
-        json = getItemListForPageWrapper(request, InventoryDataItem.SERVICES,
+        json = getItemListForPageWrapper(request, InventoryDataItem.SERVICE_TYPE_NAME,
             request.getParameter("sortBy"), request.getParameter("searchBy"));
         postLogAudit(request);
         return json;
-    }
-
+    } 
+    
+    /**
+     * Serves the aggregate count of service types
+     * 
+     * @param request HttpServletRequest
+     * 
+     * @return count of service types
+     */
+    @RequestMapping(
+        value = {SERVICE_TYPE_ID},
+        method = RequestMethod.GET,
+        produces = "application/json")
+    @ResponseBody
+    @Cacheable
+    public String getAllServiceTypeIds(HttpServletRequest request) {
+        String json = null;
+        json = getItemListForPageWrapper(request, InventoryDataItem.SERVICE_TYPE_ID,
+            request.getParameter("sortBy"), request.getParameter("searchBy"));
+        postLogAudit(request);
+        return json;
+    } 
+    
     /**
      * Gets the specified blueprint content for viewing.
      * 
@@ -679,68 +656,61 @@ public class InventoryController extends DashboardRestrictedBaseController {
      * @throws Exception On serialization failure
      */
     @RequestMapping(
-        value = {SERVICE_TYPES_PATH + "/{typeid}"},
+        value = {SERVICE_TYPES_PATH + "/{typeId}"},
         method = RequestMethod.DELETE,
         produces = "application/json")
     @ResponseBody
-    public String deleteServiceType(@PathVariable("typeid") String typeid,
-        HttpServletRequest request, HttpServletResponse response) throws Exception {
+    public String deleteServiceType(@PathVariable("typeId") String typeId,
+        HttpServletRequest request, 
+        HttpServletResponse response) throws Exception {
         preLogAudit(request);
-        String json = "{\"202\": \"OK\"}";
+        String json = "{\"204\": \"Blueprint deleted\"}";
+        boolean allow = true;
         try {
-            inventoryClient.deleteServiceType(typeid);
+            // check if these dep_ids exist in cloudify
+            List<CloudifyDeployedTenant> deplForBp = 
+                cloudifyClient.getDeploymentForBlueprint("TID-"+typeId);
+            if (deplForBp.size() > 0 ) {
+                allow = false;
+            } else {                        
+                ServiceQueryParams qryParams = 
+                    new ServiceQueryParams.Builder().typeId(typeId).build();
+                ServiceRefList srvcRefs = inventoryClient.getServicesForType(qryParams);
+                Set<String> dep_ids = srvcRefs.items.stream().map(x -> ((ServiceRef)x).id).collect(Collectors.toSet());  
+                if (dep_ids.size() > 0) {
+                    // now check again if these dep_ids still exist in cloudify
+                    List<String> allDepNames = cloudifyClient.getDeploymentNamesWithFilter(request);
+                    for (String str: dep_ids) {
+                        if (allDepNames.stream().anyMatch(s->s.equalsIgnoreCase(str))) {
+                            allow = false;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (!allow) {
+                response.setStatus(HttpStatus.SC_BAD_REQUEST);
+                json = objectMapper.writeValueAsString(
+                    new RestResponseError("Deployments exist for this blueprint"));
+                /*
+                PrintWriter out = response.getWriter();
+                response.setContentType("application/json");
+                response.setCharacterEncoding("UTF-8");
+                out.print(json);
+                out.flush();
+                */
+                return json;
+            } else {
+                inventoryClient.deleteServiceType(typeId);
+                this.cacheOwnerToBpMap();
+            }
         } catch (ServiceTypeNotFoundException | ServiceTypeAlreadyDeactivatedException e) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "DCAE Inventory");
             MDC.put("TargetServiceName", "DCAE Inventory");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting service type " + typeid + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deleteServiceType caught exception");
-            json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
-        } catch (Exception t) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "DCAE Inventory");
-            MDC.put("TargetServiceName", "DCAE Inventory");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting service type " + typeid + " failed!");
-            logger.error(EELFLoggerDelegate.errorLogger, "deleteServiceType caught exception");
-            json = objectMapper
-                .writeValueAsString(new RestResponseError("deleteDeployment failed", t));
-        } finally {
-            postLogAudit(request);
-        }
-        return json;
-    }
-
-    /**
-     * Deletes the specified service i.e. deployment from inventory
-     *
-     * @param id Service ID
-     * @param request HttpServletRequest
-     * @param response HttpServletResponse
-     * @return status code on success; error on failure.
-     * @throws Exception On serialization failure
-     */
-    @RequestMapping(
-        value = {SERVICES_PATH + "/{serviceId}"},
-        method = RequestMethod.DELETE,
-        produces = "application/json")
-    @ResponseBody
-    public String deleteService(@PathVariable("serviceId") String serviceId,
-        HttpServletRequest request, HttpServletResponse response) throws Exception {
-        preLogAudit(request);
-        String json = "{\"202\": \"OK\"}";
-        try {
-            inventoryClient.deleteService(serviceId);
-        } catch (ServiceNotFoundException | ServiceAlreadyDeactivatedException e) {
-            MDC.put(SystemProperties.STATUS_CODE, "ERROR");
-            MDC.put("TargetEntity", "DCAE Inventory");
-            MDC.put("TargetServiceName", "DCAE Inventory");
-            MDC.put("ErrorCode", "300");
-            MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting service " + serviceId + " failed!");
+            MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!");
             logger.error(EELFLoggerDelegate.errorLogger, "deleteServiceType caught exception");
             json = objectMapper.writeValueAsString(new RestResponseError(e.getMessage()));
         } catch (Exception t) {
@@ -749,10 +719,10 @@ public class InventoryController extends DashboardRestrictedBaseController {
             MDC.put("TargetServiceName", "DCAE Inventory");
             MDC.put("ErrorCode", "300");
             MDC.put("ErrorCategory", "ERROR");
-            MDC.put("ErrorDescription", "Deleting service " + serviceId + " failed!");
+            MDC.put("ErrorDescription", "Deleting service type " + typeId + " failed!");
             logger.error(EELFLoggerDelegate.errorLogger, "deleteServiceType caught exception");
             json = objectMapper
-                .writeValueAsString(new RestResponseError("deleteDeployment failed", t));
+                .writeValueAsString(new RestResponseError("delete blueprint failed", t));
         } finally {
             postLogAudit(request);
         }
@@ -778,8 +748,7 @@ public class InventoryController extends DashboardRestrictedBaseController {
         String json = "{\"201\": \"OK\"}";
         try {
             // Verify that the Service Type can be parsed for inputs.
-            Blueprint.parse(serviceType.getBlueprintTemplate());
-            // InventoryClient inventoryClient = getInventoryClient(request);
+            Blueprint.parse(serviceType.getBlueprintTemplate());  
             inventoryClient.addServiceType(serviceType);
         } catch (BlueprintParseException e) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
@@ -839,8 +808,8 @@ public class InventoryController extends DashboardRestrictedBaseController {
         String json = "{\"201\": \"OK\"}";
         try {
             Blueprint.parse(serviceTypeRequest.getBlueprintTemplate());
-            // InventoryClient inventoryClient = getInventoryClient(request);
             inventoryClient.addServiceType(serviceTypeRequest);
+            this.cacheOwnerToBpMap();
         } catch (BlueprintParseException e) {
             MDC.put(SystemProperties.STATUS_CODE, "ERROR");
             MDC.put("TargetEntity", "DCAE Inventory");
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/ControllerEndpoint.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/ControllerEndpoint.java
deleted file mode 100644 (file)
index 3e74ff4..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-
-package org.onap.ccsdk.dashboard.domain;
-
-import org.onap.portalsdk.core.domain.support.DomainVo;
-
-/**
- * Model for controller endpoint information stored in database. A single row
- * for a user represents a selected endpoint.
- */
-public class ControllerEndpoint extends DomainVo {
-
-    private static final long serialVersionUID = 8785223545128054402L;
-
-    private long userId;
-    private String name;
-    private String url;
-    private String inventoryUrl;
-    private String dhandlerUrl;
-
-    public ControllerEndpoint() {
-    }
-
-    public ControllerEndpoint(long userId, String name, String url, String inventoryUrl, String dhandlerUrl) {
-        this.userId = userId;
-        this.name = name;
-        this.url = url;
-        this.inventoryUrl = inventoryUrl;
-        this.dhandlerUrl = dhandlerUrl;
-    }
-
-    public long getUserId() {
-        return userId;
-    }
-
-    public void setUserId(long userId) {
-        this.userId = userId;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
-    public String getInventoryUrl() {
-        return inventoryUrl;
-    }
-
-    public void setInventoryUrl(String inventoryUrl) {
-        this.inventoryUrl = inventoryUrl;
-    }
-
-    public String getDhandlerUrl() {
-        return dhandlerUrl;
-    }
-
-    public void setDhandlerUrl(String dhandlerUrl) {
-        this.dhandlerUrl = dhandlerUrl;
-    }
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/EcdComponent.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/domain/EcdComponent.java
deleted file mode 100644 (file)
index c62d7bc..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-
-package org.onap.ccsdk.dashboard.domain;
-
-import org.apache.commons.lang3.StringUtils;
-import org.onap.portalsdk.core.domain.support.DomainVo;
-
-public class EcdComponent extends DomainVo {
-
-    private static final long serialVersionUID = 1L;
-
-    private Long compId;
-    private String cname; // component name
-    private String dname; // component display name
-
-    public Long getCompId() {
-        return compId;
-    }
-
-    public void setCompId(Long compId) {
-        this.compId = compId;
-    }
-
-    public String getCname() {
-        return cname;
-    }
-
-    public void setCname(String cname) {
-        this.cname = cname;
-    }
-
-    public String getDname() {
-        return dname;
-    }
-
-    public void setDname(String dname) {
-        this.dname = dname;
-    }
-
-    public boolean contains(String searchString) {
-        if (StringUtils.containsIgnoreCase(this.getCname(), searchString)
-                || StringUtils.containsIgnoreCase(this.getDname(), searchString)) {
-            return true;
-        }
-        return false;
-    }
-
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployment.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeployment.java
deleted file mode 100644 (file)
index 60bf229..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import java.util.List;
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Model with fields only for the top-level attributes. All complex child
- * structures are represented simply as generic collections.
- */
-public final class CloudifyDeployment extends ECTransportModel {
-
-    /** A unique identifier for the deployment. */
-    public final String id;
-    public final String description;
-    /** The id of the blueprint the deployment is based on. */
-    public final String blueprint_id;
-    /** The time when the deployment was created. */
-    public final String created_at;
-    /** The time the deployment was last updated at. */
-    public final String updated_at;
-    /**
-     * A dictionary containing key value pairs which represents a deployment input
-     * and its provided value.
-     */
-    public final Map<String, Object> inputs;
-    /** A dictionary containing policies of a deployment. */
-    public final Map<String, Object> policy_types;
-    /** A dictionary containing policy triggers of a deployment. */
-    public final Map<String, Object> policy_triggers;
-    /** A dictionary containing an outputs definition of a deployment. */
-    public final Map<String, Object> outputs;
-    /** A dictionary containing the groups definition of deployment. */
-    public final Map<String, Object> groups;
-
-    public final Map<String, Object> scaling_groups;
-    /** A list of workflows that can be executed on a deployment. */
-    public final List<Workflow> workflows;
-
-    public final String tenant_name;
-
-    @JsonCreator
-    public CloudifyDeployment(@JsonProperty("description") String description,
-            @JsonProperty("blueprint_id") String blueprint_id, @JsonProperty("created_at") String created_at,
-            @JsonProperty("updated_at") String updated_at, @JsonProperty("id") String id,
-            @JsonProperty("inputs") Map<String, Object> inputs,
-            @JsonProperty("policy_types") Map<String, Object> policy_types,
-            @JsonProperty("policy_triggers") Map<String, Object> policy_triggers,
-            @JsonProperty("outputs") Map<String, Object> outputs, @JsonProperty("groups") Map<String, Object> groups,
-            @JsonProperty("scaling_groups") Map<String, Object> scaling_groups,
-            @JsonProperty("workflows") List<Workflow> workflows, @JsonProperty("tenant_name") String tenant_name) {
-        this.description = description;
-        this.blueprint_id = blueprint_id;
-        this.created_at = created_at;
-        this.updated_at = updated_at;
-        this.id = id;
-        this.inputs = inputs;
-        this.policy_types = policy_types;
-        this.policy_triggers = policy_triggers;
-        this.outputs = outputs;
-        this.groups = groups;
-        this.scaling_groups = scaling_groups;
-        this.workflows = workflows;
-        this.tenant_name = tenant_name;
-    }
-
-    public static final class Inputs {
-        public final String openstack_auth_url;
-        public final String external_network_name;
-        public final String openstack_username;
-        public final String instance_image;
-        public final String keypair_name;
-        public final String instance_name;
-        public final String keypair_private_key_path;
-        public final String openstack_tenant_name;
-        public final String subnet_name;
-        public final String openstack_region;
-        public final String openstack_password;
-        public final String ssh_username;
-        public final String instance_flavor;
-        public final String network_name;
-
-        @JsonCreator
-        public Inputs(@JsonProperty("openstack_auth_url") String openstack_auth_url,
-                @JsonProperty("external_network_name") String external_network_name,
-                @JsonProperty("openstack_username") String openstack_username,
-                @JsonProperty("instance_image") String instance_image,
-                @JsonProperty("keypair_name") String keypair_name, @JsonProperty("instance_name") String instance_name,
-                @JsonProperty("keypair_private_key_path") String keypair_private_key_path,
-                @JsonProperty("openstack_tenant_name") String openstack_tenant_name,
-                @JsonProperty("subnet_name") String subnet_name,
-                @JsonProperty("openstack_region") String openstack_region,
-                @JsonProperty("openstack_password") String openstack_password,
-                @JsonProperty("ssh_username") String ssh_username,
-                @JsonProperty("instance_flavor") String instance_flavor,
-                @JsonProperty("network_name") String network_name) {
-
-            this.openstack_auth_url = openstack_auth_url;
-            this.external_network_name = external_network_name;
-            this.openstack_username = openstack_username;
-            this.instance_image = instance_image;
-            this.keypair_name = keypair_name;
-            this.instance_name = instance_name;
-            this.keypair_private_key_path = keypair_private_key_path;
-            this.openstack_tenant_name = openstack_tenant_name;
-            this.subnet_name = subnet_name;
-            this.openstack_region = openstack_region;
-            this.openstack_password = openstack_password;
-            this.ssh_username = ssh_username;
-            this.instance_flavor = instance_flavor;
-            this.network_name = network_name;
-        }
-    }
-
-    public static final class Workflow {
-        public final String name;
-        public final String created_at;
-        public final Map<String, Parameter> parameters;
-
-        @JsonCreator
-        public Workflow(@JsonProperty("name") String name, @JsonProperty("created_at") String created_at,
-                @JsonProperty("parameters") Map<String, Parameter> parameters) {
-            this.name = name;
-            this.created_at = created_at;
-            this.parameters = parameters;
-        }
-    }
-
-    public static final class Parameter {
-
-        @JsonProperty("default")
-        public final Object xdefault;
-        public final String description;
-
-        @JsonCreator
-        public Parameter(@JsonProperty("default") Object xdefault, @JsonProperty("description") String description) {
-            this.xdefault = xdefault;
-            this.description = description;
-        }
-    }
-
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentRequest.java
deleted file mode 100644 (file)
index 2110111..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Model for message POST-ed to controller to create a Cloudify Deployment:
- * 
- * <pre>
-       {
-               "deployment_id" : "deployment-id",
-               "blueprint_id" : "blueprint-id", 
-               "parameters" :
-             { 
-                "p1" : "v1"
-              }
-       }
- * </pre>
- */
-public final class CloudifyDeploymentRequest extends ECTransportModel {
-
-    /** A unique identifier for the deployment. */
-    public final String deployment_id;
-    /** A unique identifier for the blueprint. */
-    public final String blueprint_id;
-    /**
-     * These values are input for the deployment which can be retrieved from the GET
-     * /blueprint API this is :plan.input field in GET /blueprint
-     */
-    public final Map<String, Object> parameters;
-
-    @JsonCreator
-    public CloudifyDeploymentRequest(@JsonProperty("deployment_id") String deployment_id,
-            @JsonProperty("blueprint_id") String blueprint_id,
-            @JsonProperty("parameters") Map<String, Object> parameters) {
-        this.deployment_id = deployment_id;
-        this.blueprint_id = blueprint_id;
-        this.parameters = parameters;
-    }
-
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateRequest.java
deleted file mode 100644 (file)
index 16ac145..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Model for message POST-ed to controller to update a Cloudify Deployment:
- * 
- * NOTE: THIS IS NOT HOW THE REQUEST TO CLOUDIFY'S ENDPOINT LOOKS. THE REQUEST
- * IS CONSTRUCTED IN PROPER FORMAT IN THE API HANDLER
- * 
- * <pre>
- * {
-       "deployment_id" : "deployment-id",       
-       "workflow_name" : "workflow-name",
-    "allow_custom_parameter" : "true|false",
-    "force" : "true|false",
-    "node_instance_id": "node-instance-id",
-    "limits_cpu": limits_cpu,
-    "limits_mem": limits_mem,
-    "image": "image",
-    "replicas": replicas,
-    "container_name": "container_name"
-  }
- * </pre>
- */
-public final class CloudifyDeploymentUpdateRequest extends ECTransportModel {
-
-    /** A unique identifier for the deployment. */
-    public final String deployment_id;
-    /** A unique identifier for the workflow */
-    public final String workflow_name;
-    public final Boolean allow_custom_parameter;
-    public final Boolean force;
-    /** Parameters: retrieve using the GET /deployments */
-    // public final Map<String, Object> parameters;
-    public final String node_instance_id;
-    public final String limits_cpu;
-    public final String limits_mem;
-    public final String image;
-    public final Number replicas;
-    public final String container_name;
-
-    @JsonCreator
-    public CloudifyDeploymentUpdateRequest(@JsonProperty("deployment_id") String deployment_id,
-            @JsonProperty("workflow_name") String workflow_name,
-            @JsonProperty("allow_custom_parameter") Boolean allowCustomParameter, @JsonProperty("force") Boolean force,
-            @JsonProperty("node_instance_id") String node_instance_id, @JsonProperty("limits_cpu") String limits_cpu,
-            @JsonProperty("limits_mem") String limits_mem, @JsonProperty("image") String image,
-            @JsonProperty("replicas") Number replicas, @JsonProperty("container_name") String container_name) {
-
-        this.deployment_id = deployment_id;
-        this.workflow_name = workflow_name;
-        this.allow_custom_parameter = allowCustomParameter;
-        this.force = force;
-        // this.parameters = parameters;
-        this.node_instance_id = node_instance_id;
-        this.limits_cpu = limits_cpu;
-        this.limits_mem = limits_mem;
-        this.image = image;
-        this.replicas = replicas;
-        this.container_name = container_name;
-    }
-
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateResponse.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpdateResponse.java
deleted file mode 100644 (file)
index 65688bb..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Model with fields only for the top-level attributes. All complex child
- * structures are represented simply as generic collections.
- */
-public final class CloudifyDeploymentUpdateResponse extends ECTransportModel {
-
-    /** A unique identifier for the execution. */
-    public final String id;
-    /** The executions status. */
-    public final String status;
-    /** The time the execution was queued at. */
-    public final String created_at;
-    /** The id/name of the workflow the execution is of. */
-    public final String workflow_id;
-    /** true if the execution is of a system workflow. */
-    public final Boolean is_system_workflow;
-    /** The id of the blueprint the execution is in the context of. */
-    public final String blueprint_id;
-    /** The id of the deployment the execution is in the context of. */
-    public final String deployment_id;
-    /** The execution’s error message on execution failure. */
-    public final String error;
-    /** A dict of the workflow parameters passed when starting the execution. */
-    public final Map<String, Object> parameters;
-
-    public final String tenant_name;
-
-    public final String created_by;
-
-    public final Boolean private_resource;
-
-    public final String resource_availability;
-
-    @JsonCreator
-    public CloudifyDeploymentUpdateResponse(@JsonProperty("status") String status,
-            @JsonProperty("created_at") String created_at, @JsonProperty("workflow_id") String workflow_id,
-            @JsonProperty("is_system_workflow") Boolean is_system_workflow,
-            @JsonProperty("blueprint_id") String blueprint_id, @JsonProperty("deployment_id") String deployment_id,
-            @JsonProperty("error") String error, @JsonProperty("id") String id,
-            @JsonProperty("parameters") Map<String, Object> parameters, @JsonProperty("tenant_name") String tenant_name,
-            @JsonProperty("created_by") String created_by, @JsonProperty("private_resource") Boolean private_resource,
-            @JsonProperty("resource_availability") String resource_availability) {
-
-        this.status = status;
-        this.created_at = created_at;
-        this.workflow_id = workflow_id;
-        this.is_system_workflow = is_system_workflow;
-        this.blueprint_id = blueprint_id;
-        this.deployment_id = deployment_id;
-        this.error = error;
-        this.id = id;
-        this.parameters = parameters;
-        this.tenant_name = tenant_name;
-        this.created_by = created_by;
-        this.private_resource = private_resource;
-        this.resource_availability = resource_availability;
-    }
-
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpgradeRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyDeploymentUpgradeRequest.java
deleted file mode 100644 (file)
index 30d3d16..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Model for message POST-ed to controller to execute upgrade workflow on a
- * Cloudify Deployment:
- * 
- * NOTE: THIS IS NOT HOW THE REQUEST TO CLOUDIFY'S ENDPOINT LOOKS. THE REQUEST
- * IS CONSTRUCTED IN PROPER FORMAT IN THE API HANDLER
- * 
- * <pre>
-*              {
-                               "config_url": config_url,
-                               "config_format": config_format,
-                               "chartRepo": chartRepo,
-                               "chartVersion": chartVersion
-               };
- * </pre>
- */
-public final class CloudifyDeploymentUpgradeRequest extends ECTransportModel {
-
-    public final String config_url;
-    public final String config_format;
-    public final String chartRepo;
-    public final String chartVersion;
-
-    @JsonCreator
-    public CloudifyDeploymentUpgradeRequest(@JsonProperty("config_url") String config_url,
-            @JsonProperty("config_format") String config_format, @JsonProperty("chartRepo") String chartRepo,
-            @JsonProperty("chartVersion") String chartVersion) {
-
-        this.config_url = config_url;
-        this.config_format = config_format;
-        this.chartRepo = chartRepo;
-        this.chartVersion = chartVersion;
-    }
-
-    public String getConfig_url() {
-        return config_url;
-    }
-
-    public String getConfig_format() {
-        return config_format;
-    }
-
-    public String getChartRepo() {
-        return chartRepo;
-    }
-
-    public String getChartVersion() {
-        return chartVersion;
-    }
-
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyEvent.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyEvent.java
deleted file mode 100644 (file)
index d95ff24..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class CloudifyEvent extends ECTransportModel {
-
-    /** The id of the blueprint the execution is in the context of. */
-    public final String blueprint_id;
-    /** The id of the deployment the execution is in the context of. */
-    public final String deployment_id;
-    /** List of errors that happened while executing a given task */
-    public final List<CloudifyErrorCause> error_causes;
-    /** The executions status. */
-    public final String event_type;
-    /** The time the execution was queued at. */
-    public final String execution_id;
-    /** log level */
-    public final String level;
-    /** logger id */
-    public final String logger;
-    /** message text */
-    public final String message;
-    /** node instance id */
-    public final String node_instance_id;
-    /** node name */
-    public final String node_name;
-    /** Operation path */
-    public final String operation;
-    /** time at which the event occurred on the executing machine */
-    public final String reported_timestamp;
-    /** time at which the event was logged on the management machine */
-    public final String timestamp;
-    /** resource is a cloudify_event or a cloudify_log */
-    public final String type;
-    /** The id/name of the workflow the execution is of. */
-    public final String workflow_id;
-
-    @JsonCreator
-    public CloudifyEvent(@JsonProperty("blueprint_id") String blueprint_id,
-            @JsonProperty("deployment_id") String deployment_id,
-            @JsonProperty("error_causes") List<CloudifyErrorCause> error_causes,
-            @JsonProperty("event_type") String event_type, @JsonProperty("execution_id") String execution_id,
-            @JsonProperty("level") String level, @JsonProperty("logger") String logger,
-            @JsonProperty("message") String message, @JsonProperty("node_instance_id") String node_instance_id,
-            @JsonProperty("node_name") String node_name, @JsonProperty("operation") String operation,
-            @JsonProperty("reported_timestamp") String reported_timestamp, @JsonProperty("timestamp") String timestamp,
-            @JsonProperty("type") String type, @JsonProperty("workflow_id") String workflow_id) {
-
-        this.blueprint_id = blueprint_id;
-        this.deployment_id = deployment_id;
-        this.error_causes = (error_causes == null) ? new LinkedList<CloudifyErrorCause>() : error_causes;
-        this.event_type = event_type;
-        this.execution_id = execution_id;
-        this.level = level;
-        this.logger = logger;
-        this.message = message;
-        this.node_instance_id = node_instance_id;
-        this.node_name = node_name;
-        this.operation = operation;
-        this.reported_timestamp = reported_timestamp;
-        this.timestamp = timestamp;
-        this.type = type;
-        this.workflow_id = workflow_id;
-    }
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecution.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecution.java
deleted file mode 100644 (file)
index 3fe393d..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Model with fields only for the top-level attributes. All complex child
- * structures are represented simply as generic collections.
- */
-public final class CloudifyExecution extends ECTransportModel {
-
-    /** A unique identifier for the execution. */
-    public final String id;
-    /** The executions status. */
-    public final String status;
-    /** The time the execution was queued at. */
-    public final String created_at;
-    /** The id/name of the workflow the execution is of. */
-    public final String workflow_id;
-    /** true if the execution is of a system workflow. */
-    public final Boolean is_system_workflow;
-    /** The id of the blueprint the execution is in the context of. */
-    public final String blueprint_id;
-    /** The id of the deployment the execution is in the context of. */
-    public final String deployment_id;
-    /** The tenant used to deploy */
-    public final String tenant_name;
-    /** The execution’s error message on execution failure. */
-    public final String error;
-    /** A dict of the workflow parameters passed when starting the execution. */
-    public final Map<String, Object> parameters;
-    /** true if helm plugin is used */
-    public Boolean is_helm;
-    /** true if helm status is enabled */
-    public Boolean helm_status;
-
-    @JsonCreator
-    public CloudifyExecution(@JsonProperty("status") String status, @JsonProperty("created_at") String created_at,
-            @JsonProperty("workflow_id") String workflow_id,
-            @JsonProperty("is_system_workflow") Boolean is_system_workflow,
-            @JsonProperty("blueprint_id") String blueprint_id, @JsonProperty("deployment_id") String deployment_id,
-            @JsonProperty("tenant_name") String tenant_name, @JsonProperty("error") String error,
-            @JsonProperty("id") String id, @JsonProperty("parameters") Map<String, Object> parameters,
-            @JsonProperty("is_helm") Boolean is_helm, @JsonProperty("helm_status") Boolean helm_status) {
-
-        this.status = status;
-        this.created_at = created_at;
-        this.workflow_id = workflow_id;
-        this.is_system_workflow = is_system_workflow;
-        this.blueprint_id = blueprint_id;
-        this.deployment_id = deployment_id;
-        this.tenant_name = tenant_name;
-        this.error = error;
-        this.id = id;
-        this.parameters = parameters;
-        this.is_helm = is_helm;
-        this.helm_status = helm_status;
-    }
-
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecutionRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyExecutionRequest.java
deleted file mode 100644 (file)
index a9bad02..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- *  
- *  Modifications Copyright (C) 2019 IBM
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class CloudifyExecutionRequest extends ECTransportModel {
-
-    /** A unique identifier for the deployment. */
-    public String deployment_id;
-    /** A unique identifier for the workflow */
-    public String workflow_id;
-    public Boolean allow_custom_parameters;
-    public Boolean force;
-    public String tenant;
-    /** Parameters: retrieve using the GET /deployments */
-    public Map<String, Object> parameters;
-    
-    @JsonCreator
-    public CloudifyExecutionRequest(@JsonProperty("deployment_id") String deployment_id,
-            @JsonProperty("workflow_id") String workflow_id,
-            @JsonProperty("allow_custom_parameters") Boolean allowCustomParameters,
-            @JsonProperty("force") Boolean force, @JsonProperty("tenant") String tenant,
-            @JsonProperty("parameters") Map<String, Object> parameters) {
-        this.deployment_id = deployment_id;
-        this.workflow_id = workflow_id;
-        this.allow_custom_parameters = allowCustomParameters;
-        this.force = force;
-        this.tenant = tenant;
-        this.parameters = parameters;
-    }
-
-    public String getDeployment_id() {
-        return deployment_id;
-    }
-
-    public String getWorkflow_id() {
-        return workflow_id;
-    }
-
-    public Boolean getAllow_custom_parameters() {
-        return allow_custom_parameters;
-    }
-
-    public Boolean getForce() {
-        return force;
-    }
-
-    public String getTenant() {
-        return tenant;
-    }
-
-    public Map<String, Object> getParameters() {
-        return parameters;
-    }
-
-    public void setDeployment_id(String deployment_id) {
-        this.deployment_id = deployment_id;
-    }
-
-    public void setWorkflow_id(String workflow_id) {
-        this.workflow_id = workflow_id;
-    }
-
-    public void setAllow_custom_parameters(Boolean allow_custom_parameters) {
-        this.allow_custom_parameters = allow_custom_parameters;
-    }
-
-    public void setForce(Boolean force) {
-        this.force = force;
-    }
-
-    public void setTenant(String tenant) {
-        this.tenant = tenant;
-    }
-
-    public void setParameters(Map<String, Object> parameters) {
-        this.parameters = parameters;
-    }
-
-
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceId.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifyNodeInstanceId.java
deleted file mode 100644 (file)
index abe25fc..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Model with fields only for the top-level attributes. All complex child
- * structures are represented as generic collections.
- */
-public final class CloudifyNodeInstanceId extends ECTransportModel {
-
-    /** The id of the node instance. */
-    public final String id;
-
-    /** The name of the user that created the node instance */
-    // public final String created_by;
-    /** The id of the deployment the node instance belongs to. */
-    // public final String deployment_id;
-    /** The Compute node instance id the node is contained within. */
-    // public final String host_id;
-    /** The relationships the node has with other nodes. */
-    // public final List relationships;
-    /** The runtime properties of the node instance. */
-    // public final String runtime_properties;
-    /** The node instance state. */
-    // public final String state;
-    /** The name of the tenant that owns the node instance. */
-
-    // public final String tenant_name;
-    /**
-     * A version attribute used for optimistic locking when updating the node
-     * instance.
-     */
-    // public final String version;
-
-    @JsonCreator
-    public CloudifyNodeInstanceId(@JsonProperty("id") String id) {
-        this.id = id;
-    }
-
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecret.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecret.java
deleted file mode 100644 (file)
index 594ebfa..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class CloudifySecret extends ECTransportModel {
-
-    /** The time when the secret was created */
-    public final String created_at;
-    /** The secret’s key, unique per tenant */
-    public final String key;
-    /** The time the secret was last updated at */
-    public final String updated_at;
-    /** The secret’s value */
-    public final String value;
-    /** Defines who can see the secret. Can be private, tenant or global */
-    public final String visibility;
-    /** Determines who can see the value of the secret. */
-    public final String is_hidden_value;
-
-    @JsonCreator
-    public CloudifySecret(@JsonProperty("created_at") String created_at, @JsonProperty("key") String key,
-            @JsonProperty("updated_at") String updated_at, @JsonProperty("value") String value,
-            @JsonProperty("visibility") String visibility, @JsonProperty("is_hidden_value") String is_hidden_value) {
-        this.created_at = created_at;
-        this.key = key;
-        this.updated_at = updated_at;
-        this.value = value;
-        this.visibility = visibility;
-        this.is_hidden_value = is_hidden_value;
-    }
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecretUpload.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/CloudifySecretUpload.java
deleted file mode 100644 (file)
index 3026a7a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class CloudifySecretUpload extends ECTransportModel {
-
-    /** The secret's name */
-    public final String name;
-    /** The secret’s value */
-    public final String value;
-    /** Update value if secret already exists */
-    public final boolean update_if_exists;
-    /** Defines who can see the secret. Can be private, tenant or global */
-    public final String visibility;
-    /** Determines who can see the value of the secret. */
-    public final boolean is_hidden_value;
-    /** The tenant name for this secret */
-    public final String tenant;
-
-    @JsonCreator
-    public CloudifySecretUpload(@JsonProperty("name") String name, @JsonProperty("value") String value,
-            @JsonProperty("update_if_exists") boolean update_if_exists, @JsonProperty("visibility") String visibility,
-            @JsonProperty("is_hidden_value") boolean is_hidden_value, @JsonProperty("tenant") String tenant) {
-        this.name = name;
-        this.value = value;
-        this.update_if_exists = update_if_exists;
-        this.visibility = visibility;
-        this.is_hidden_value = is_hidden_value;
-        this.tenant = tenant;
-    }
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointCredentials.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointCredentials.java
deleted file mode 100644 (file)
index 03159c2..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import org.onap.portalsdk.core.onboarding.util.CipherUtil;
-
-/**
- * Model with Controller username and password for use only within the back end;
- * never serialized as JSON.
- */
-public class ControllerEndpointCredentials extends ControllerEndpointTransport {
-
-    public String username;
-    public String password;
-    public boolean isEncryptedPass;
-
-    public ControllerEndpointCredentials(boolean selected, String name, String url, String inventoryUrl,
-            String dhandlerUrl, String consulUrl, String username, String password, boolean isEncryptedPass) {
-        super(selected, name, url, inventoryUrl, dhandlerUrl, consulUrl);
-        this.username = username;
-        this.password = password;
-        this.isEncryptedPass = isEncryptedPass;
-    }
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
-    public String getPassword() {
-        return password;
-    }
-
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
-    public boolean getEncryptedPassword() {
-        return isEncryptedPass;
-    }
-
-    public void setEncryptedPassword(boolean isEncryptedPass) {
-        this.isEncryptedPass = isEncryptedPass;
-    }
-
-    /**
-     * Convenience method to yield a ControllerEndpointTransport object.
-     * 
-     * @return ControllerEndpoint with copy of the non-privileged data
-     */
-    public ControllerEndpointTransport toControllerEndpointTransport() {
-        return new ControllerEndpointTransport(getSelected(), getName(), getUrl(), getInventoryUrl(), getDhandlerUrl(),
-                getConsulUrl());
-    }
-
-    /**
-     * Accepts clear text and stores an encrypted value; as a side effect, sets the
-     * encrypted flag to true.
-     * 
-     * @param plainText Clear-text password
-     * @throws Exception If encryption fails
-     */
-    public void encryptPassword(final String plainText) throws Exception {
-        this.password = CipherUtil.encrypt(plainText);
-        this.isEncryptedPass = true;
-    }
-
-    /**
-     * Client should call this method if {@link #getEncryptedPassword()} returns
-     * true.
-     * 
-     * @return Clear-text password.
-     * @throws Exception If decryption fails
-     */
-    public String decryptPassword() throws Exception {
-        return CipherUtil.decrypt(password);
-    }
-}
\ No newline at end of file
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointTransport.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerEndpointTransport.java
deleted file mode 100644 (file)
index 56019c9..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-/**
- * Model for message passed by backend to frontend about ECOMP-C Endpoints.
- */
-public class ControllerEndpointTransport extends ECTransportModel {
-
-    private boolean selected;
-    private String name;
-    private String url;
-    private String inventoryUrl;
-    private String dhandlerUrl;
-    private String consulUrl;
-
-    public ControllerEndpointTransport() {
-    }
-
-    public ControllerEndpointTransport(boolean selected, String name, String url, String inventoryUrl,
-            String dhandlerUrl, String consulUrl) {
-        this.selected = selected;
-        this.name = name;
-        this.url = url;
-        this.inventoryUrl = inventoryUrl;
-        this.dhandlerUrl = dhandlerUrl;
-        this.consulUrl = consulUrl;
-    }
-
-    public boolean getSelected() {
-        return selected;
-    }
-
-    public void setSelected(boolean selected) {
-        this.selected = selected;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
-    public String getInventoryUrl() {
-        return inventoryUrl;
-    }
-
-    public void setInventoryUrl(String inventoryUrl) {
-        this.inventoryUrl = inventoryUrl;
-    }
-
-    public String getDhandlerUrl() {
-        return dhandlerUrl;
-    }
-
-    public void setDhandlerUrl(String dhandlerUrl) {
-        this.dhandlerUrl = dhandlerUrl;
-    }
-
-    public String getConsulUrl() {
-        return consulUrl;
-    }
-
-    public void setConsulUrl(String consulUrl) {
-        this.consulUrl = consulUrl;
-    }
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerOpsTools.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/ControllerOpsTools.java
deleted file mode 100644 (file)
index 1bc8702..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-/**
- * Model for message passed by backend to frontend about OPS Tools URLs.
- */
-public class ControllerOpsTools extends ECTransportModel {
-
-    private String id;
-    private String url;
-
-    public ControllerOpsTools() {
-    }
-
-    public ControllerOpsTools(String id, String url) {
-        this.setId(id);
-        this.setUrl(url);
-    }
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
-}
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import java.util.Map;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
@@ -32,30 +34,30 @@ import com.fasterxml.jackson.annotation.JsonProperty;
  */
 public final class CloudifyBlueprint extends ECTransportModel {
 
-    /** A unique identifier for the blueprint. */
-    public final String id;
-    /** The blueprint’s main file name. */
-    public final String main_file_name;
-    /** The blueprint’s description. */
-    public final String description;
-    /** The time the blueprint was uploaded to the manager. */
-    public final String created_at;
-    /** The last time the blueprint was updated. */
-    public final String updated_at;
-    /** The parsed result of the blueprint. */
-    public final Map<String, Object> plan;
+       /** A unique identifier for the blueprint. */
+       public final String id;
+       /** The blueprint’s main file name. */
+       public final String main_file_name;
+       /** The blueprint’s description. */
+       public final String description;
+       /** The time the blueprint was uploaded to the manager. */
+       public final String created_at;
+       /** The last time the blueprint was updated. */
+       public final String updated_at;
+       /** The parsed result of the blueprint. */
+       public final Map<String, Object> plan;
 
-    @JsonCreator
-    public CloudifyBlueprint(@JsonProperty("main_file_name") String main_file_name,
-            @JsonProperty("description") String description, @JsonProperty("created_at") String created_at,
-            @JsonProperty("updated_at") String updated_at, @JsonProperty("id") String id,
-            @JsonProperty("plan") Map<String, Object> plan) {
-        this.main_file_name = main_file_name;
-        this.description = description;
-        this.created_at = created_at;
-        this.updated_at = updated_at;
-        this.id = id;
-        this.plan = plan;
-    }
+       @JsonCreator
+       public CloudifyBlueprint(@JsonProperty("main_file_name") String main_file_name,
+                       @JsonProperty("description") String description, @JsonProperty("created_at") String created_at,
+                       @JsonProperty("updated_at") String updated_at, @JsonProperty("id") String id,
+                       @JsonProperty("plan") Map<String, Object> plan) {
+               this.main_file_name = main_file_name;
+               this.description = description;
+               this.created_at = created_at;
+               this.updated_at = updated_at;
+               this.id = id;
+               this.plan = plan;
+       }
 
 }
@@ -1,4 +1,3 @@
-
 /*******************************************************************************
  * =============LICENSE_START=========================================================
  *
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import java.util.List;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyBlueprintList extends ECTransportModel {
-
-    public final List<CloudifyBlueprint> items;
-    public final Metadata metadata;
+       
+       public final List<CloudifyBlueprint> items;
+       public final Metadata metadata;
 
     @JsonCreator
-    public CloudifyBlueprintList(@JsonProperty("items") List<CloudifyBlueprint> items,
-            @JsonProperty("metadata") Metadata metadata) {
-        this.items = items;
-        this.metadata = metadata;
-    }
-
-    public static final class Metadata {
-        public final Pagination pagination;
+    public CloudifyBlueprintList(@JsonProperty("items") List<CloudifyBlueprint> items, @JsonProperty("metadata") Metadata metadata){
+               this.items = items;
+               this.metadata = metadata;
+       }
+    
+       public static final class Metadata {
+               public final Pagination pagination;
 
         @JsonCreator
-        public Metadata(@JsonProperty("pagination") Pagination pagination) {
+        public Metadata(@JsonProperty("pagination") Pagination pagination){
             this.pagination = pagination;
         }
-
-        public static final class Pagination {
-            public final long total;
-            public final long offset;
-            public final long size;
+        
+               public static final class Pagination {
+                       public final long total;
+                       public final long offset;
+                       public final long size;
 
             @JsonCreator
-            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset,
-                    @JsonProperty("size") long size) {
-                this.total = total;
-                this.offset = offset;
-                this.size = size;
-            }
-        }
-    }
-
+            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){
+                               this.total = total;
+                               this.offset = offset;
+                               this.size = size;
+                       }
+               }
+       }
+       
 }
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployedTenant.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployedTenant.java
new file mode 100644 (file)
index 0000000..a895dd0
--- /dev/null
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ *******************************************************************************/
+package org.onap.ccsdk.dashboard.model.cloudify;
+
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class CloudifyDeployedTenant extends ECTransportModel {
+       
+       /** A unique identifier for the deployment. */
+       public final String id;
+       /** tenant where the deployment was done */
+       public final String tenant_name;
+       public final String created_at;
+    public final String updated_at;
+       
+       @JsonCreator
+       public CloudifyDeployedTenant(@JsonProperty("id") String id,
+                       @JsonProperty("tenant_name") String tenant_name,
+                       @JsonProperty("created_at") String created_at,
+                       @JsonProperty("updated_at") String updated_at) {
+               this.id = id;
+               this.tenant_name = tenant_name;
+               this.created_at = created_at;
+               this.updated_at = updated_at;
+       }
+       
+          /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((created_at == null) ? 0 : created_at.hashCode());
+        result = prime * result + ((id == null) ? 0 : id.hashCode());
+        result = prime * result + ((tenant_name == null) ? 0 : tenant_name.hashCode());
+        result = prime * result + ((updated_at == null) ? 0 : updated_at.hashCode());
+        return result;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        CloudifyDeployedTenant other = (CloudifyDeployedTenant) obj;
+        if (created_at == null) {
+            if (other.created_at != null)
+                return false;
+        } else if (!created_at.equals(other.created_at))
+            return false;
+        if (id == null) {
+            if (other.id != null)
+                return false;
+        } else if (!id.equals(other.id))
+            return false;
+        if (tenant_name == null) {
+            if (other.tenant_name != null)
+                return false;
+        } else if (!tenant_name.equals(other.tenant_name))
+            return false;
+        if (updated_at == null) {
+            if (other.updated_at != null)
+                return false;
+        } else if (!updated_at.equals(other.updated_at))
+            return false;
+        return true;
+    }
+
+}
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import java.util.List;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyDeployedTenantList extends ECTransportModel {
-    public final List<CloudifyDeployedTenant> items;
-    public final Metadata metadata;
+       public final List<CloudifyDeployedTenant> items;
+       public final Metadata metadata;
 
     @JsonCreator
-    public CloudifyDeployedTenantList(@JsonProperty("items") List<CloudifyDeployedTenant> items,
-            @JsonProperty("metadata") Metadata metadata) {
-        this.items = items;
-        this.metadata = metadata;
-    }
+    public CloudifyDeployedTenantList(@JsonProperty("items") List<CloudifyDeployedTenant> items, @JsonProperty("metadata") Metadata metadata){
+               this.items = items;
+               this.metadata = metadata;
+       }
 
-    public static final class Metadata {
-        public final Pagination pagination;
+       public static final class Metadata {
+               public final Pagination pagination;
 
         @JsonCreator
-        public Metadata(@JsonProperty("pagination") Pagination pagination) {
+        public Metadata(@JsonProperty("pagination") Pagination pagination){
             this.pagination = pagination;
         }
-
-        public static final class Pagination {
-            public final long total;
-            public final long offset;
-            public final long size;
+        
+               public static final class Pagination {
+                       public final long total;
+                       public final long offset;
+                       public final long size;
 
             @JsonCreator
-            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset,
-                    @JsonProperty("size") long size) {
-                this.total = total;
-                this.offset = offset;
-                this.size = size;
-            }
-        }
-    }
+            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){
+                               this.total = total;
+                               this.offset = offset;
+                               this.size = size;
+                       }
+               }
+       }
 }
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployment.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyDeployment.java
new file mode 100644 (file)
index 0000000..94ccf7d
--- /dev/null
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+  *******************************************************************************/
+package org.onap.ccsdk.dashboard.model.cloudify;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Model with fields only for the top-level attributes. All complex child
+ * structures are represented simply as generic collections.
+ */
+public final class CloudifyDeployment extends ECTransportModel {
+
+       /** A unique identifier for the deployment. */
+       public final String id;
+       public final String description;
+       /** The id of the blueprint the deployment is based on. */
+       public final String blueprint_id;
+       /** The time when the deployment was created. */
+       public final String created_at;
+       /** The time the deployment was last updated at. */
+       public final String updated_at;
+       /**
+        * A dictionary containing key value pairs which represents a deployment
+        * input and its provided value.
+        */
+       public final Map<String, Object> inputs;
+       /** A dictionary containing policies of a deployment. */
+       public final Map<String, Object> policy_types;
+       /** A dictionary containing policy triggers of a deployment. */
+       public final Map<String, Object> policy_triggers;
+       /** A dictionary containing an outputs definition of a deployment. */
+       public final Map<String, Object> outputs;
+       /** A dictionary containing the groups definition of deployment. */
+       public final Map<String, Object> groups;
+
+       public final Map<String, Object> scaling_groups;
+       /** A list of workflows that can be executed on a deployment. */
+       public final List<Workflow> workflows;
+
+       public final String tenant_name;
+       
+    /** internal role based setting */
+    public boolean canDeploy;
+    
+    /** latest execution object */
+    public CloudifyExecution lastExecution;
+    /** install execution workflow status */
+       //public String installStatus;
+    /** true if helm plugin is used */
+    public Boolean isHelm;
+    /** true if helm status is enabled */
+    public Boolean helmStatus;
+    /** Consul service health status */
+    public String healthStatus;
+    /** blueprint owner */
+    public String owner;
+
+       @JsonCreator
+       public CloudifyDeployment(@JsonProperty("description") String description,
+                       @JsonProperty("blueprint_id") String blueprint_id, @JsonProperty("created_at") String created_at,
+                       @JsonProperty("updated_at") String updated_at, @JsonProperty("id") String id,
+                       @JsonProperty("inputs") Map<String, Object> inputs, @JsonProperty("policy_types") Map<String, Object> policy_types,
+                       @JsonProperty("policy_triggers") Map<String, Object> policy_triggers,
+                       @JsonProperty("outputs") Map<String, Object> outputs, @JsonProperty("groups") Map<String, Object> groups,
+                       @JsonProperty("scaling_groups") Map<String, Object> scaling_groups,
+                       @JsonProperty("workflows") List<Workflow> workflows, @JsonProperty("tenant_name") String tenant_name) {
+               this.description = description;
+               this.blueprint_id = blueprint_id;
+               this.created_at = created_at;
+               this.updated_at = updated_at;
+               this.id = id;
+               this.inputs = inputs;
+               this.policy_types = policy_types;
+               this.policy_triggers = policy_triggers;
+               this.outputs = outputs;
+               this.groups = groups;
+               this.scaling_groups = scaling_groups;
+               this.workflows = workflows;
+               this.tenant_name = tenant_name;
+       }
+
+       public static final class Inputs {
+               public final String openstack_auth_url;
+               public final String external_network_name;
+               public final String openstack_username;
+               public final String instance_image;
+               public final String keypair_name;
+               public final String instance_name;
+               public final String keypair_private_key_path;
+               public final String openstack_tenant_name;
+               public final String subnet_name;
+               public final String openstack_region;
+               public final String openstack_password;
+               public final String ssh_username;
+               public final String instance_flavor;
+               public final String network_name;
+
+               @JsonCreator
+               public Inputs(@JsonProperty("openstack_auth_url") String openstack_auth_url,
+                               @JsonProperty("external_network_name") String external_network_name,
+                               @JsonProperty("openstack_username") String openstack_username,
+                               @JsonProperty("instance_image") String instance_image,
+                               @JsonProperty("keypair_name") String keypair_name, @JsonProperty("instance_name") String instance_name,
+                               @JsonProperty("keypair_private_key_path") String keypair_private_key_path,
+                               @JsonProperty("openstack_tenant_name") String openstack_tenant_name,
+                               @JsonProperty("subnet_name") String subnet_name,
+                               @JsonProperty("openstack_region") String openstack_region,
+                               @JsonProperty("openstack_password") String openstack_password,
+                               @JsonProperty("ssh_username") String ssh_username,
+                               @JsonProperty("instance_flavor") String instance_flavor,
+                               @JsonProperty("network_name") String network_name) {
+
+                       this.openstack_auth_url = openstack_auth_url;
+                       this.external_network_name = external_network_name;
+                       this.openstack_username = openstack_username;
+                       this.instance_image = instance_image;
+                       this.keypair_name = keypair_name;
+                       this.instance_name = instance_name;
+                       this.keypair_private_key_path = keypair_private_key_path;
+                       this.openstack_tenant_name = openstack_tenant_name;
+                       this.subnet_name = subnet_name;
+                       this.openstack_region = openstack_region;
+                       this.openstack_password = openstack_password;
+                       this.ssh_username = ssh_username;
+                       this.instance_flavor = instance_flavor;
+                       this.network_name = network_name;
+               }
+       }
+
+       public static final class Workflow {
+               public final String name;
+               public final String created_at;
+               public final Map<String,Parameter> parameters;
+
+               @JsonCreator
+               public Workflow(@JsonProperty("name") String name, @JsonProperty("created_at") String created_at,
+                               @JsonProperty("parameters") Map<String,Parameter> parameters) {
+                       this.name = name;
+                       this.created_at = created_at;
+                       this.parameters = parameters;
+               }
+       }
+
+       public static final class Parameter {
+               
+               @JsonProperty("default")
+               public final Object xdefault;
+               public final String description;
+
+               @JsonCreator
+               public Parameter(@JsonProperty("default") Object xdefault, @JsonProperty("description") String description) {
+                       this.xdefault = xdefault;
+                       this.description = description;
+               }
+       }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((id == null) ? 0 : id.hashCode());
+        result = prime * result + ((tenant_name == null) ? 0 : tenant_name.hashCode());
+        return result;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        CloudifyDeployment other = (CloudifyDeployment) obj;
+        if (id == null) {
+            if (other.id != null)
+                return false;
+        } else if (!id.equals(other.id))
+            return false;
+        if (tenant_name == null) {
+            if (other.tenant_name != null)
+                return false;
+        } else if (!tenant_name.equals(other.tenant_name))
+            return false;
+        return true;
+    }
+
+}
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
 
-public class CloudifyDeployedTenant extends ECTransportModel {
+public class CloudifyDeploymentExt extends ECTransportModel {
 
     /** A unique identifier for the deployment. */
-    public final String id;
-    /** tenant where the deployment was done */
-    public final String tenant_name;
-    /** The id of the blueprint the deployment is based on. */
-    public final String blueprint_id;
-
-    @JsonCreator
-    public CloudifyDeployedTenant(@JsonProperty("id") String id, @JsonProperty("blueprint_id") String blueprint_id,
-            @JsonProperty("tenant_name") String tenant_name) {
+    public String id;
+    /** blueprint ID for the deployment */
+    public String bp_id;
+    public String tenant;
+    /** latest execution object */
+    public CloudifyExecution lastExecution;
+    /** true if helm plugin is used */
+    public Boolean isHelm;
+    /** true if helm status is enabled */
+    public Boolean helmStatus;
+    
+    public CloudifyDeploymentExt(String id, String bp_id, String tenant) {
+        super();
         this.id = id;
-        this.blueprint_id = blueprint_id;
-        this.tenant_name = tenant_name;
+        this.bp_id = bp_id;
+        this.tenant = tenant;
     }
 }
@@ -2,7 +2,7 @@
  * =============LICENSE_START=========================================================
  *
  * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
 
-import java.util.List;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
-import org.onap.ccsdk.dashboard.domain.EcdComponent;
+public class CloudifyDeploymentHelm {
 
-public class EcdAppComponent {
-
-    public String app;
-
-    public List<EcdComponent> comps;
-
-    /*
-     * @JsonCreator public EcdAppComponent(@JsonProperty("app") String app,
-     * 
-     * @JsonProperty("comps") List<EcdComponent> comps) { this(app, comps); }
-     */
-    public EcdAppComponent(String app, List<EcdComponent> comps) {
-        this.app = app;
-        this.comps = comps;
+    /** A unique identifier for the deployment. */
+    public String id;
+    /** true if helm plugin is used */
+    public Boolean isHelm;
+    /** true if helm status is enabled */
+    public Boolean helmStatus;
+    
+    public CloudifyDeploymentHelm(String id, Boolean isHelm, Boolean helmStatus) {
+        super();
+        this.id = id;
+        this.isHelm = isHelm;
+        this.helmStatus = helmStatus;
     }
+    
+    
 }
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import java.util.List;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-public class CloudifySecretList extends ECTransportModel {
-    public final List<CloudifySecret> items;
-    public final Metadata metadata;
+public class CloudifyDeploymentList extends ECTransportModel {
+       
+       public final List<CloudifyDeployment> items;
+       public final Metadata metadata;
 
     @JsonCreator
-    public CloudifySecretList(@JsonProperty("items") List<CloudifySecret> items,
-            @JsonProperty("metadata") Metadata metadata) {
-        this.items = items;
-        this.metadata = metadata;
-    }
+    public CloudifyDeploymentList(@JsonProperty("items") List<CloudifyDeployment> items, @JsonProperty("metadata") Metadata metadata){
+               this.items = items;
+               this.metadata = metadata;
+       }
 
-    public static final class Metadata {
-        public final Pagination pagination;
+       public static final class Metadata {
+               public final Pagination pagination;
 
         @JsonCreator
-        public Metadata(@JsonProperty("pagination") Pagination pagination) {
+        public Metadata(@JsonProperty("pagination") Pagination pagination){
             this.pagination = pagination;
         }
-
-        public static final class Pagination {
-            public final long total;
-            public final long offset;
-            public final long size;
+        
+               public static final class Pagination {
+                       public final long total;
+                       public final long offset;
+                       public final long size;
 
             @JsonCreator
-            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset,
-                    @JsonProperty("size") long size) {
-                this.total = total;
-                this.offset = offset;
-                this.size = size;
-            }
-        }
-    }
+            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){
+                               this.total = total;
+                               this.offset = offset;
+                               this.size = size;
+                       }
+               }
+       }
+               
 }
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyErrorCause extends ECTransportModel {
 
-    /** Error message */
-    public final String message;
-
-    /** Stack trace at the point where the exception was raised */
-    public final String traceback;
-
-    /** Exception type */
-    public final String type;
-
-    @JsonCreator
-    public CloudifyErrorCause(@JsonProperty("message") String message, @JsonProperty("traceback") String traceback,
-            @JsonProperty("type") String type) {
-
-        this.message = message;
-        this.traceback = traceback;
-        this.type = type;
-    }
-
-    @Override
-    public String toString() {
-        return "CloudifyErrorCause [message=" + message + ", traceback=" + traceback + ", type=" + type + "]";
-    }
+       /** Error message */
+       public final String message;
+       
+       /** Stack trace at the point where the exception was raised */
+       public final String traceback;
+       
+       /** Exception type */
+       public final String type;
+       
+       @JsonCreator
+       public CloudifyErrorCause(
+                       @JsonProperty("message") String message, 
+                       @JsonProperty("traceback") String traceback,
+                       @JsonProperty("type") String type) {
+
+               this.message = message;
+               this.traceback = traceback;
+               this.type = type;
+       }
+
+       @Override
+       public String toString() {
+               return "CloudifyErrorCause [message=" + message + ", traceback=" + traceback + ", type=" + type + "]";
+       }
 }
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyEvent.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyEvent.java
new file mode 100644 (file)
index 0000000..a6593ab
--- /dev/null
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.ccsdk.dashboard.model.cloudify;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class CloudifyEvent extends ECTransportModel {
+
+       /** The id of the blueprint the execution is in the context of. */
+       public final String blueprint_id;
+       /** The id of the deployment the execution is in the context of. */
+       public final String deployment_id;
+       /** List of errors that happened while executing a given task */
+       public final List<CloudifyErrorCause> error_causes;
+       /** The executions status. */
+       public final String event_type;
+       /** The time the execution was queued at. */
+       public final String execution_id;
+       /** log level */
+       public final String level;
+       /** logger id */
+       public final String logger;
+       /** message text */
+       public final String message;
+       /** node instance id */
+       public final String node_instance_id;
+       /** node name */
+       public final String node_name;
+       /** Operation path */
+       public final String operation;
+       /** time at which the event occurred on the executing machine */
+       public final String reported_timestamp;
+       /**  time at which the event was logged on the management machine */
+       public final String timestamp;
+       /** resource is a cloudify_event or a cloudify_log */
+       public final String type;
+       /** The id/name of the workflow the execution is of. */
+       public final String workflow_id;
+
+       @JsonCreator
+       public CloudifyEvent(
+                       @JsonProperty("blueprint_id") String blueprint_id, 
+                       @JsonProperty("deployment_id") String deployment_id,
+                       @JsonProperty("error_causes") List<CloudifyErrorCause> error_causes,
+                       @JsonProperty("event_type") String event_type,
+                       @JsonProperty("execution_id") String execution_id, 
+                       @JsonProperty("level") String level,
+                       @JsonProperty("logger") String logger, 
+                       @JsonProperty("message") String message,
+                       @JsonProperty("node_instance_id") String node_instance_id,
+                       @JsonProperty("node_name") String node_name,
+                       @JsonProperty("operation") String operation,
+                       @JsonProperty("reported_timestamp") String reported_timestamp,
+                       @JsonProperty("timestamp") String timestamp,
+                       @JsonProperty("type")  String type,
+                       @JsonProperty("workflow_id") String workflow_id) {
+
+               this.blueprint_id = blueprint_id;
+               this.deployment_id = deployment_id;
+               this.error_causes = (error_causes == null) ? new LinkedList<CloudifyErrorCause> () : error_causes;
+               this.event_type = event_type;
+               this.execution_id = execution_id;
+               this.level = level;
+               this.logger = logger;
+               this.message = message;
+               this.node_instance_id = node_instance_id;
+               this.node_name = node_name;
+               this.operation = operation;
+               this.reported_timestamp = reported_timestamp;
+               this.timestamp = timestamp;
+               this.type = type;
+               this.workflow_id = workflow_id;
+       }
+}
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import java.util.List;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyEventList extends ECTransportModel {
 
-    public final List<CloudifyEvent> items;
-    public final Metadata metadata;
+       public final List<CloudifyEvent> items;
+       public final Metadata metadata;
 
     @JsonCreator
-    public CloudifyEventList(@JsonProperty("items") List<CloudifyEvent> items,
-            @JsonProperty("metadata") Metadata metadata) {
-        this.items = items;
-        this.metadata = metadata;
-    }
+    public CloudifyEventList(@JsonProperty("items") List<CloudifyEvent> items, @JsonProperty("metadata") Metadata metadata){
+               this.items = items;
+               this.metadata = metadata;
+       }
 
-    public static final class Metadata {
-        public final Pagination pagination;
+       public static final class Metadata {
+               public final Pagination pagination;
 
         @JsonCreator
-        public Metadata(@JsonProperty("pagination") Pagination pagination) {
+        public Metadata(@JsonProperty("pagination") Pagination pagination){
             this.pagination = pagination;
         }
-
-        public static final class Pagination {
-            public final long total;
-            public final long offset;
-            public final long size;
+        
+               public static final class Pagination {
+                       public final long total;
+                       public final long offset;
+                       public final long size;
 
             @JsonCreator
-            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset,
-                    @JsonProperty("size") long size) {
-                this.total = total;
-                this.offset = offset;
-                this.size = size;
-            }
-        }
-    }
+            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){
+                               this.total = total;
+                               this.offset = offset;
+                               this.size = size;
+                       }
+               }
+       }
 }
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecution.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecution.java
new file mode 100644 (file)
index 0000000..366a43d
--- /dev/null
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.ccsdk.dashboard.model.cloudify;
+
+import java.util.Map;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Model with fields only for the top-level attributes. All complex child
+ * structures are represented simply as generic collections.
+ */
+public final class CloudifyExecution extends ECTransportModel {
+
+       /** A unique identifier for the execution. */
+       public final String id;
+       /** The executions status. */
+       public final String status;
+       /** The time the execution was queued at. */
+       public final String created_at;
+       /** The time the execution ended in successful, failed or cancelled state */
+       public final String ended_at;
+       /** The id/name of the workflow the execution is of. */
+       public final String workflow_id;
+       /** true if the execution is of a system workflow. */
+       public final Boolean is_system_workflow;
+       /** The id of the blueprint the execution is in the context of. */
+       public final String blueprint_id;
+       /** The id of the deployment the execution is in the context of. */
+       public final String deployment_id;
+       /** The tenant used to deploy */
+       public final String tenant_name;
+       /** The execution’s error message on execution failure. */
+       public final String error;
+       /** A dict of the workflow parameters passed when starting the execution. */
+       public final Map<String, Object> parameters;
+
+       @JsonCreator
+       public CloudifyExecution(@JsonProperty("status") String status, 
+               @JsonProperty("created_at") String created_at,
+               @JsonProperty("ended_at") String ended_at,
+                       @JsonProperty("workflow_id") String workflow_id,
+                       @JsonProperty("is_system_workflow") Boolean is_system_workflow,
+                       @JsonProperty("blueprint_id") String blueprint_id, 
+                       @JsonProperty("deployment_id") String deployment_id,
+                       @JsonProperty("tenant_name") String tenant_name,
+                       @JsonProperty("error") String error, @JsonProperty("id") String id,
+                       @JsonProperty("parameters") Map<String, Object> parameters) {
+
+               this.status = status;
+               this.created_at = created_at;
+               this.ended_at = ended_at;
+               this.workflow_id = workflow_id;
+               this.is_system_workflow = is_system_workflow;
+               this.blueprint_id = blueprint_id;
+               this.deployment_id = deployment_id;
+               this.tenant_name = tenant_name;
+               this.error = error;
+               this.id = id;
+               this.parameters = parameters;
+       }
+
+}
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import java.util.List;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyExecutionList extends ECTransportModel {
-
-    public final List<CloudifyExecution> items;
-    public final Metadata metadata;
+       
+       public final List<CloudifyExecution> items;
+       public final Metadata metadata;
 
     @JsonCreator
-    public CloudifyExecutionList(@JsonProperty("items") List<CloudifyExecution> items,
-            @JsonProperty("metadata") Metadata metadata) {
-        this.items = items;
-        this.metadata = metadata;
-    }
+    public CloudifyExecutionList(@JsonProperty("items") List<CloudifyExecution> items, @JsonProperty("metadata") Metadata metadata){
+               this.items = items;
+               this.metadata = metadata;
+       }
 
-    public static final class Metadata {
-        public final Pagination pagination;
+       public static final class Metadata {
+               public final Pagination pagination;
 
         @JsonCreator
-        public Metadata(@JsonProperty("pagination") Pagination pagination) {
+        public Metadata(@JsonProperty("pagination") Pagination pagination){
             this.pagination = pagination;
         }
-
-        public static final class Pagination {
-            public final long total;
-            public final long offset;
-            public final long size;
+        
+               public static final class Pagination {
+                       public final long total;
+                       public final long offset;
+                       public final long size;
 
             @JsonCreator
-            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset,
-                    @JsonProperty("size") long size) {
-                this.total = total;
-                this.offset = offset;
-                this.size = size;
-            }
-        }
-    }
-
+            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){
+                               this.total = total;
+                               this.offset = offset;
+                               this.size = size;
+                       }
+               }
+       }
+               
 }
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecutionRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifyExecutionRequest.java
new file mode 100644 (file)
index 0000000..41b034c
--- /dev/null
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.ccsdk.dashboard.model.cloudify;
+
+import java.util.Map;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class CloudifyExecutionRequest extends ECTransportModel {
+
+       /** A unique identifier for the deployment. */
+       public String deployment_id;
+       /** A unique identifier for the workflow */
+       public String workflow_id;
+       public Boolean allow_custom_parameters;
+       public Boolean force;
+       public String tenant;
+       /** Parameters: retrieve using the GET /deployments */
+       public Map<String, Object> parameters;
+       
+       public String getDeployment_id() {
+               return deployment_id;
+       }
+
+       public String getWorkflow_id() {
+               return workflow_id;
+       }
+
+       public Boolean getAllow_custom_parameters() {
+               return allow_custom_parameters;
+       }
+
+       public Boolean getForce() {
+               return force;
+       }
+
+       public String getTenant() {
+               return tenant;
+       }
+
+       public Map<String, Object> getParameters() {
+               return parameters;
+       }
+
+       public void setDeployment_id(String deployment_id) {
+               this.deployment_id = deployment_id;
+       }
+
+       public void setWorkflow_id(String workflow_id) {
+               this.workflow_id = workflow_id;
+       }
+
+       public void setAllow_custom_parameters(Boolean allow_custom_parameters) {
+               this.allow_custom_parameters = allow_custom_parameters;
+       }
+
+       public void setForce(Boolean force) {
+               this.force = force;
+       }
+
+       public void setTenant(String tenant) {
+               this.tenant = tenant;
+       }
+
+       public void setParameters(Map<String, Object> parameters) {
+               this.parameters = parameters;
+       }
+
+       @JsonCreator
+       public CloudifyExecutionRequest(@JsonProperty("deployment_id") String deployment_id,
+                       @JsonProperty("workflow_id") String workflow_id,
+                       @JsonProperty("allow_custom_parameters") Boolean allowCustomParameters, 
+                       @JsonProperty("force") Boolean force,
+                       @JsonProperty("tenant") String tenant,
+                       @JsonProperty("parameters") Map<String, Object> parameters) {
+               this.deployment_id = deployment_id;
+               this.workflow_id = workflow_id;
+               this.allow_custom_parameters = allowCustomParameters;
+               this.force = force;
+               this.tenant = tenant;
+               this.parameters = parameters;
+       }
+
+}
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyNodeId extends ECTransportModel {
-    /** The id of the node */
-    public final String id;
-
-    @JsonCreator
-    public CloudifyNodeId(@JsonProperty("id") String id) {
-        this.id = id;
-    }
+       /** The id of the node */
+       public final String id;
+       
+       @JsonCreator
+       public CloudifyNodeId(@JsonProperty("id") String id) {
+               this.id = id;
+       }
 
 }
@@ -19,7 +19,7 @@
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import java.util.List;
 
@@ -28,36 +28,34 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyNodeIdList {
 
-    public final List<CloudifyNodeId> items;
-    public final Metadata metadata;
+       public final List<CloudifyNodeId> items;
+       public final Metadata metadata;
 
     @JsonCreator
-    public CloudifyNodeIdList(@JsonProperty("items") List<CloudifyNodeId> items,
-            @JsonProperty("metadata") Metadata metadata) {
-        this.items = items;
-        this.metadata = metadata;
-    }
-
-    public static final class Metadata {
-        public final Pagination pagination;
+    public CloudifyNodeIdList(@JsonProperty("items") List<CloudifyNodeId> items, @JsonProperty("metadata") Metadata metadata){
+               this.items = items;
+               this.metadata = metadata;
+       }
+    
+       public static final class Metadata {
+               public final Pagination pagination;
 
         @JsonCreator
-        public Metadata(@JsonProperty("pagination") Pagination pagination) {
+        public Metadata(@JsonProperty("pagination") Pagination pagination){
             this.pagination = pagination;
         }
-
-        public static final class Pagination {
-            public final long total;
-            public final long offset;
-            public final long size;
+        
+               public static final class Pagination {
+                       public final long total;
+                       public final long offset;
+                       public final long size;
 
             @JsonCreator
-            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset,
-                    @JsonProperty("size") long size) {
-                this.total = total;
-                this.offset = offset;
-                this.size = size;
-            }
-        }
-    }
+            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){
+                               this.total = total;
+                               this.offset = offset;
+                               this.size = size;
+                       }
+               }
+       }
 }
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
-import java.util.List;
 import java.util.Map;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyNodeInstance extends ECTransportModel {
 
-    /** The id of the node instance. */
-    public final String id;
-
-    /** The runtime properties of the node instance. */
-    public final Map<String, Object> runtime_properties;
+       /** The id of the node instance. */
+       public final String id;
+       
+       /** The runtime properties of the node instance. */
+       public final Map<String, Object> runtime_properties;
 
-    @JsonCreator
-    public CloudifyNodeInstance(@JsonProperty("id") String id,
-            @JsonProperty("runtime_properties") Map<String, Object> runtime_properties) {
-        this.id = id;
-        this.runtime_properties = runtime_properties;
-    }
+       @JsonCreator
+       public CloudifyNodeInstance(@JsonProperty("id") String id,
+                       @JsonProperty("runtime_properties") Map<String, Object> runtime_properties) {
+                               this.id = id;
+                               this.runtime_properties = runtime_properties;
+       }
 }
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 /**
- * Trivial wrapper for Blueprint YAML content.
+ * Model with fields only for the top-level attributes. All complex child
+ * structures are represented as generic collections.
  */
-public final class CloudifyBlueprintContent extends ECTransportModel {
-
-    /** A unique identifier for the blueprint. */
-    public final String id;
-    /** The content of the blueprint as YAML */
-    public final String content;
+public final class CloudifyNodeInstanceId extends ECTransportModel {
 
-    @JsonCreator
-    public CloudifyBlueprintContent(@JsonProperty("id") String id, @JsonProperty("content") String content) {
-        this.id = id;
-        this.content = content;
-    }
+       /** The id of the node instance. */
+       public final String id;
+       
+       @JsonCreator
+       public CloudifyNodeInstanceId(@JsonProperty("id") String id) {
+               this.id = id;
+       }
 
 }
@@ -1,4 +1,3 @@
-
 /*******************************************************************************
  * =============LICENSE_START=========================================================
  *
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import java.util.List;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyNodeInstanceIdList extends ECTransportModel {
-
-    public final List<CloudifyNodeInstanceId> items;
-    public final Metadata metadata;
+       
+       public final List<CloudifyNodeInstanceId> items;
+       public final Metadata metadata;
 
     @JsonCreator
-    public CloudifyNodeInstanceIdList(@JsonProperty("items") List<CloudifyNodeInstanceId> items,
-            @JsonProperty("metadata") Metadata metadata) {
-        this.items = items;
-        this.metadata = metadata;
-    }
-
-    public static final class Metadata {
-        public final Pagination pagination;
+    public CloudifyNodeInstanceIdList(@JsonProperty("items") List<CloudifyNodeInstanceId> items, @JsonProperty("metadata") Metadata metadata){
+               this.items = items;
+               this.metadata = metadata;
+       }
+    
+       public static final class Metadata {
+               public final Pagination pagination;
 
         @JsonCreator
-        public Metadata(@JsonProperty("pagination") Pagination pagination) {
+        public Metadata(@JsonProperty("pagination") Pagination pagination){
             this.pagination = pagination;
         }
-
-        public static final class Pagination {
-            public final long total;
-            public final long offset;
-            public final long size;
+        
+               public static final class Pagination {
+                       public final long total;
+                       public final long offset;
+                       public final long size;
 
             @JsonCreator
-            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset,
-                    @JsonProperty("size") long size) {
-                this.total = total;
-                this.offset = offset;
-                this.size = size;
-            }
-        }
-    }
-
+            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){
+                               this.total = total;
+                               this.offset = offset;
+                               this.size = size;
+                       }
+               }
+       }
+       
 }
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import java.util.List;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyNodeInstanceList extends ECTransportModel {
 
-    public final List<CloudifyNodeInstance> items;
-    public final Metadata metadata;
+       public final List<CloudifyNodeInstance> items;
+       public final Metadata metadata;
 
     @JsonCreator
-    public CloudifyNodeInstanceList(@JsonProperty("items") List<CloudifyNodeInstance> items,
-            @JsonProperty("metadata") Metadata metadata) {
-        this.items = items;
-        this.metadata = metadata;
-    }
-
-    public static final class Metadata {
-        public final Pagination pagination;
+    public CloudifyNodeInstanceList(@JsonProperty("items") List<CloudifyNodeInstance> items, @JsonProperty("metadata") Metadata metadata){
+               this.items = items;
+               this.metadata = metadata;
+       }
+    
+       public static final class Metadata {
+               public final Pagination pagination;
 
         @JsonCreator
-        public Metadata(@JsonProperty("pagination") Pagination pagination) {
+        public Metadata(@JsonProperty("pagination") Pagination pagination){
             this.pagination = pagination;
         }
-
-        public static final class Pagination {
-            public final long total;
-            public final long offset;
-            public final long size;
+        
+               public static final class Pagination {
+                       public final long total;
+                       public final long offset;
+                       public final long size;
 
             @JsonCreator
-            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset,
-                    @JsonProperty("size") long size) {
-                this.total = total;
-                this.offset = offset;
-                this.size = size;
-            }
-        }
-    }
+            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){
+                               this.total = total;
+                               this.offset = offset;
+                               this.size = size;
+                       }
+               }
+       }
 }
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-/**
- * Model for message POST-ed to controller to create a Cloudify Blueprint:
- * 
- * <pre>
-  {
-       "blueprint_id" : "blueprint-id",
-       "blueprint_filename" : "name.yaml",
-       "zip_url" : "url"
-  }
- * </pre>
+public class CloudifyPlugin {
+/*
+ *          "uploaded_at": "2020-04-29T14:46:59.628Z",
+            "package_version": "1.7.2",
+            "package_name": "k8splugin",
+            "distribution": "centos",
+            "supported_platform": "linux_x86_64",
  */
-public final class CloudifyBlueprintUpload extends ECTransportModel {
-
-    /** A unique identifier for the blueprint. */
-    public final String blueprint_id;
-    /** The blueprint’s main file name. */
-    public final String blueprint_filename;
-    /** The zip file URL. */
-    public final String zip_url;
-
+    public final String package_name;
+    
+    public final String package_version;
+    
+    public final String supported_platform;
+    
+    public final String distribution;
+    
+    public final String uploaded_at;
+    
     @JsonCreator
-    public CloudifyBlueprintUpload(@JsonProperty("blueprint_id") String blueprint_id,
-            @JsonProperty("blueprint_filename") String blueprint_filename, @JsonProperty("zip_url") String zip_url) {
-        this.blueprint_id = blueprint_id;
-        this.blueprint_filename = blueprint_filename;
-        this.zip_url = zip_url;
+    public CloudifyPlugin(
+            @JsonProperty("package_name") String package_name,
+            @JsonProperty("package_version") String package_version,
+            @JsonProperty("supported_platform") String supported_platform,
+            @JsonProperty("distribution") String distribution,
+            @JsonProperty("uploaded_at") String uploaded_at)  {
+        this.package_name = package_name;
+        this.package_version = package_version;
+        this.supported_platform = supported_platform;
+        this.distribution = distribution;
+        this.uploaded_at = uploaded_at;
     }
-
 }
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import java.util.List;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-public class CloudifyDeploymentList extends ECTransportModel {
-
-    public final List<CloudifyDeployment> items;
+public class CloudifyPluginList extends ECTransportModel {
+    public final List<CloudifyPlugin> items;
     public final Metadata metadata;
 
     @JsonCreator
-    public CloudifyDeploymentList(@JsonProperty("items") List<CloudifyDeployment> items,
-            @JsonProperty("metadata") Metadata metadata) {
+    public CloudifyPluginList(@JsonProperty("items") List<CloudifyPlugin> items, @JsonProperty("metadata") Metadata metadata){
         this.items = items;
         this.metadata = metadata;
     }
@@ -42,23 +42,21 @@ public class CloudifyDeploymentList extends ECTransportModel {
         public final Pagination pagination;
 
         @JsonCreator
-        public Metadata(@JsonProperty("pagination") Pagination pagination) {
+        public Metadata(@JsonProperty("pagination") Pagination pagination){
             this.pagination = pagination;
         }
-
+        
         public static final class Pagination {
             public final long total;
             public final long offset;
             public final long size;
 
             @JsonCreator
-            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset,
-                    @JsonProperty("size") long size) {
+            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){
                 this.total = total;
                 this.offset = offset;
                 this.size = size;
             }
         }
     }
-
 }
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifySecret.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/cloudify/CloudifySecret.java
new file mode 100644 (file)
index 0000000..d087ce3
--- /dev/null
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.ccsdk.dashboard.model.cloudify;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class CloudifySecret extends ECTransportModel {
+
+       /** The time when the secret was created */
+       public final String created_at;
+       /** The secret’s key, unique per tenant */
+       public final String key;
+    /** The time the secret was last updated at */
+       public final String updated_at;
+       /** The secret’s value */
+       public final String value;
+       /** Defines who can see the secret. Can be private, tenant or global*/
+       public final String visibility;
+       /** Determines who can see the value of the secret. */
+       public final String is_hidden_value;
+
+       public final String tenant_name;
+       
+       public final String resource_availability;
+       
+       @JsonCreator
+       public CloudifySecret(
+                       @JsonProperty("created_at") String created_at,
+                       @JsonProperty("key") String key,
+                       @JsonProperty("updated_at") String updated_at,
+                       @JsonProperty("value") String value,
+                       @JsonProperty("visibility") String visibility,
+                       @JsonProperty("is_hidden_value") String is_hidden_value,
+                       @JsonProperty("tenant_name") String tenant_name,
+                       @JsonProperty("resource_availability") String resource_availability)  {
+               this.created_at = created_at;
+               this.key = key;
+               this.updated_at = updated_at;
+               this.value = value;
+               this.visibility = visibility;
+               this.is_hidden_value = is_hidden_value;
+               this.tenant_name = tenant_name;
+               this.resource_availability = resource_availability;
+       }
+       
+          /**
+     * @return the key
+     */
+    public String getKey() {
+        return key;
+    }
+
+    /**
+     * @return the value
+     */
+    public String getValue() {
+        return value;
+    }
+}
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
+
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyTenant extends ECTransportModel {
 
-    /** A unique identifier for the tenant */
-    public final String id;
-    /** The tenant's name. */
-    public final String name;
-    /** tenant display name */
-    public String dName;
-
-    @JsonCreator
-    public CloudifyTenant(@JsonProperty("name") String name, @JsonProperty("dName") String dName,
-            @JsonProperty("id") String id) {
-        this.name = name;
-        this.dName = dName;
-        this.id = id;
-    }
+       /** A unique identifier for the tenant */
+       public final String id;
+       /** The tenant's name. */
+       public final String name;
+       /** tenant display name */
+       public String dName;
+       
+       @JsonCreator
+       public CloudifyTenant(@JsonProperty("name") String name,
+                       @JsonProperty("dName") String dName,
+                       @JsonProperty("id") String id) {
+               this.name = name;
+               this.dName = dName;
+               this.id = id;
+       }
 }
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
 import java.util.List;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public class CloudifyTenantList extends ECTransportModel {
-    public final List<CloudifyTenant> items;
-    public final Metadata metadata;
+       public final List<CloudifyTenant> items;
+       public final Metadata metadata;
 
     @JsonCreator
-    public CloudifyTenantList(@JsonProperty("items") List<CloudifyTenant> items,
-            @JsonProperty("metadata") Metadata metadata) {
-        this.items = items;
-        this.metadata = metadata;
-    }
-
-    public static final class Metadata {
-        public final Pagination pagination;
+    public CloudifyTenantList(@JsonProperty("items") List<CloudifyTenant> items, @JsonProperty("metadata") Metadata metadata){
+               this.items = items;
+               this.metadata = metadata;
+       }
+    
+       public static final class Metadata {
+               public final Pagination pagination;
 
         @JsonCreator
-        public Metadata(@JsonProperty("pagination") Pagination pagination) {
+        public Metadata(@JsonProperty("pagination") Pagination pagination){
             this.pagination = pagination;
         }
-
-        public static final class Pagination {
-            public final long total;
-            public final long offset;
-            public final long size;
+        
+               public static final class Pagination {
+                       public final long total;
+                       public final long offset;
+                       public final long size;
 
             @JsonCreator
-            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset,
-                    @JsonProperty("size") long size) {
-                this.total = total;
-                this.offset = offset;
-                this.size = size;
-            }
-        }
-    }
+            public Pagination(@JsonProperty("total") long total, @JsonProperty("offset") long offset, @JsonProperty("size") long size){
+                               this.total = total;
+                               this.offset = offset;
+                               this.size = size;
+                       }
+               }
+       }
 }
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model.inventory;
+package org.onap.ccsdk.dashboard.model.cloudify;
 
-import java.util.Set;
+import java.util.Collection;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
-public class ServiceGroupByResults {
+public class ServiceRefCfyList {
+    /** Number of Service objects */
+    public final Integer totalCount;
+    /** Collection containing all of the returned Service objects */
+    public final Collection<CloudifyDeployedTenant> items;
 
-    /** Property name of the service that the group by operation was performed on */
-    public String propertyName;
-    /** Set of Service objects that have the aforementioned propertyName */
-    public Set<InventoryProperty> propertyValues;
+    /**
+     * @return the items
+     */
+    public Collection<CloudifyDeployedTenant> getItems() {
+        return items;
+    }
 
     @JsonCreator
-    public ServiceGroupByResults(@JsonProperty("propertyName") String propertyName,
-            @JsonProperty("propertyValues") Set<InventoryProperty> propertyValues) {
-        this.propertyName = propertyName;
-        this.propertyValues = propertyValues;
+    public ServiceRefCfyList(
+        @JsonProperty("items") Collection<CloudifyDeployedTenant> items,
+        @JsonProperty("totalCount") Integer totalCount) {
+        this.items = items;
+        this.totalCount = totalCount;
     }
 }
@@ -19,7 +19,9 @@
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.consul;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulDeploymentHealth.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulDeploymentHealth.java
new file mode 100644 (file)
index 0000000..6837b8d
--- /dev/null
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.ccsdk.dashboard.model.consul;
+
+public class ConsulDeploymentHealth {
+    
+    private final String node;
+    private final String checkID;
+    private final String name;
+    private final String status;
+    private final String serviceID;
+    private final String serviceName;
+    
+    private ConsulDeploymentHealth(String node, String checkID, String name, String status,
+        String serviceID, String serviceName) {
+        this.node = node;
+        this.checkID = checkID;
+        this.name = name;
+        this.status = status;
+        this.serviceID = serviceID;
+        this.serviceName = serviceName;
+    }
+    
+    public String getNode() {
+        return node;
+    }
+
+    public String getCheckID() {
+        return checkID;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public String getServiceID() {
+        return serviceID;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public static class Builder {
+        private final String node;
+        private final String checkID;
+        private final String name;
+        private final String status;
+        private final String serviceID;
+        private final String serviceName;
+        
+        public Builder(ConsulServiceHealth input) {
+            this.node = input.node;
+            this.checkID = input.checkID;
+            this.name = input.name;
+            this.status = input.status;
+            this.serviceID = input.serviceID;
+            this.serviceName = input.serviceName;
+        }
+        
+        public ConsulDeploymentHealth build() {
+            return new ConsulDeploymentHealth(node, checkID, name,status, serviceID, serviceName);
+        }
+
+        public String getNode() {
+            return node;
+        }
+
+        public String getCheckID() {
+            return checkID;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getStatus() {
+            return status;
+        }
+
+        public String getServiceID() {
+            return serviceID;
+        }
+
+        public String getServiceName() {
+            return serviceName;
+        }
+    }
+}
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.consul;
 
 import java.util.List;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.consul;
 
 import java.util.Map;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceCatalogItem.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/consul/ConsulServiceCatalogItem.java
new file mode 100644 (file)
index 0000000..a5bfc3d
--- /dev/null
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.ccsdk.dashboard.model.consul;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ConsulServiceCatalogItem {
+
+    public final String node;
+    public final String address;
+    public final String datacenter;
+    public final String serviceName;
+    public final String serviceAddress;
+    public final String servicePort;
+
+    @JsonCreator
+    public ConsulServiceCatalogItem(@JsonProperty("Node") String node, @JsonProperty("Address") String address,
+            @JsonProperty("Datacenter") String datacenter, @JsonProperty("ServiceName") String serviceName,
+            @JsonProperty("ServiceAddress") String serviceAddress, @JsonProperty("ServicePort") String servicePort ) {
+        this.node = node;
+        this.address = address;
+        this.datacenter = datacenter;
+        this.serviceName = serviceName;
+        this.serviceAddress = serviceAddress;
+        this.servicePort = servicePort;
+    }
+
+    public String getNode() {
+        return node;
+    }
+
+    public String getAddress() {
+        return address;
+    }
+
+    public String getDatacenter() {
+        return datacenter;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public String getServiceAddress() {
+        return serviceAddress;
+    }
+
+    public String getServicePort() {
+        return servicePort;
+    }
+    
+}
@@ -19,7 +19,9 @@
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.consul;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
@@ -53,6 +55,8 @@ public final class ConsulServiceHealth extends ECTransportModel {
     public final String output;
     public final String serviceID;
     public final String serviceName;
+    public final String[] serviceTags;
+    public String tenant;
     public final int createIndex;
     public final int modifyIndex;
 
@@ -61,7 +65,7 @@ public final class ConsulServiceHealth extends ECTransportModel {
             @JsonProperty("Name") String name, @JsonProperty("Status") String status,
             @JsonProperty("Notes") String notes, @JsonProperty("Output") String output,
             @JsonProperty("ServiceID") String serviceID, @JsonProperty("ServiceName") String serviceName,
-            @JsonProperty("CreateIndex") int createIndex, @JsonProperty("ModifyIndex") int modifyIndex) {
+            @JsonProperty("ServiceTags") String[] serviceTags, @JsonProperty("CreateIndex") int createIndex, @JsonProperty("ModifyIndex") int modifyIndex) {
         this.node = node;
         this.checkID = checkID;
         this.name = name;
@@ -70,8 +74,28 @@ public final class ConsulServiceHealth extends ECTransportModel {
         this.output = output;
         this.serviceID = serviceID;
         this.serviceName = serviceName;
+        this.serviceTags = serviceTags;
         this.createIndex = createIndex;
         this.modifyIndex = modifyIndex;
+        ConstructTenant();
+    }
+    
+    /*
+     * Search the service tags to find and
+     * construct cfy tenant
+     */
+    private void ConstructTenant() {
+       String tenantString = "";
+       for (String tag : serviceTags) {
+               if (tag.contains("cfytenantname=")) {
+                       tenantString = tag;
+                       break;
+               }
+       }
+       if (!tenantString.equals(""))
+               tenant = tenantString.substring(tenantString.indexOf("=") + 1);
+       else
+               tenant = "";
     }
 
 }
@@ -19,7 +19,9 @@
  *
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.consul;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
  *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
 
-package org.onap.ccsdk.dashboard.model;
+package org.onap.ccsdk.dashboard.model.consul;
 
 import java.util.List;
 
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
index 7e93d9c..33dfb6a 100644 (file)
@@ -21,6 +21,8 @@
  *******************************************************************************/
 package org.onap.ccsdk.dashboard.model.deploymenthandler;
 
+import java.util.Collection;
+import java.util.LinkedList;
 import java.util.Map;
 import java.util.Optional;
 
@@ -77,11 +79,32 @@ public class DeploymentInput {
      */
     private final Map<String, Object> inputs;
 
+    private final Collection<String> reinstall_list;
+    
+    private final boolean skip_install;
+    
+    private final boolean skip_uninstall;
+    
+    private final boolean skip_reinstall;
+
+    private final boolean force;
+    
+    private final boolean ignore_failure;
+    
+    private final boolean install_first;
+    
     @JsonCreator
     public DeploymentInput(@JsonProperty("component") String component, @JsonProperty("tag") String tag,
             @JsonProperty("blueprintName") String blueprintName,
             @JsonProperty("blueprintVersion") Integer blueprintVersion, @JsonProperty("blueprintId") String blueprintId,
-            @JsonProperty("inputs") Map<String, Object> inputs, @JsonProperty("tenant") String tenant) {
+            @JsonProperty("inputs") Map<String, Object> inputs, @JsonProperty("tenant") String tenant,
+            @JsonProperty("reinstall_list") Collection<String> reinstallList, 
+            @JsonProperty("skip_install") boolean skipInstall, 
+            @JsonProperty("skip_uninstall") boolean skipUninstall, 
+            @JsonProperty("skip_reinstall") boolean skipReinstall, 
+            @JsonProperty("force") boolean force, 
+            @JsonProperty("ignore_failure") boolean ignoreFailure, 
+            @JsonProperty("install_first") boolean installFirst) {
         this.component = component;
         this.tag = tag;
         this.blueprintName = blueprintName;
@@ -89,6 +112,13 @@ public class DeploymentInput {
         this.blueprintId = Optional.ofNullable(blueprintId);
         this.inputs = inputs;
         this.tenant = tenant;
+        this.reinstall_list = (reinstallList == null) ? new LinkedList<String>() : reinstallList;
+        this.skip_install = skipInstall;
+        this.skip_uninstall = skipUninstall;
+        this.skip_reinstall = skipReinstall;
+        this.force = force;
+        this.ignore_failure = ignoreFailure;
+        this.install_first = installFirst;
     }
 
     public String getBlueprintName() {
@@ -118,4 +148,32 @@ public class DeploymentInput {
     public Optional<String> getBlueprintId() {
         return blueprintId;
     }
+    
+    public Collection<String> getReinstall_list() {
+        return reinstall_list;
+    }
+
+    public boolean isSkip_install() {
+        return skip_install;
+    }
+
+    public boolean isSkip_uninstall() {
+        return skip_uninstall;
+    }
+
+    public boolean isSkip_reinstall() {
+        return skip_reinstall;
+    }
+
+    public boolean isForce() {
+        return force;
+    }
+
+    public boolean isIgnore_failure() {
+        return ignore_failure;
+    }
+
+    public boolean isInstall_first() {
+        return install_first;
+    }
 }
index b0ac9e9..94bb064 100644 (file)
@@ -57,10 +57,10 @@ public class DeploymentRequest {
      * deployed.
      */
     private final Map<String, Object> inputs;
-
+       
     @JsonCreator
     public DeploymentRequest(@JsonProperty("serviceTypeId") String serviceTypeId,
-            @JsonProperty("inputs") Map<String, Object> inputs) {
+            @JsonProperty("inputs") Map<String, Object> inputs ) {
         this.serviceTypeId = serviceTypeId;
         this.inputs = inputs;
     }
@@ -72,4 +72,5 @@ public class DeploymentRequest {
     public Map<String, Object> getInputs() {
         return this.inputs;
     }
+
 }
index ae229b2..0bb6f74 100644 (file)
  *******************************************************************************/
 package org.onap.ccsdk.dashboard.model.deploymenthandler;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
 import java.util.Map;
+import java.util.Optional;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
@@ -69,15 +73,60 @@ public class DeploymentRequestObject {
      */
     private final Map<String, Object> inputs;
 
+    private final Collection<String> reinstall_list;
+    
+    private final boolean skip_install;
+    
+    private final boolean skip_uninstall;
+    
+    private final boolean skip_reinstall;
+
+    private final boolean force;
+    
+    private final boolean ignore_failure;
+    
+    private final boolean install_first;
+    
     @JsonCreator
     public DeploymentRequestObject(@JsonProperty("deploymentId") String deploymentId,
             @JsonProperty("serviceTypeId") String serviceTypeId, @JsonProperty("inputs") Map<String, Object> inputs,
-            @JsonProperty("tenant") String tenant, @JsonProperty("method") String method) {
+            @JsonProperty("tenant") String tenant, @JsonProperty("method") String method,
+            @JsonProperty("reinstall_list") Collection<String> reinstallList, 
+            @JsonProperty("skip_install") boolean skipInstall, 
+            @JsonProperty("skip_uninstall") boolean skipUninstall, 
+            @JsonProperty("skip_reinstall") boolean skipReinstall, 
+            @JsonProperty("force") boolean force, 
+            @JsonProperty("ignore_failure") boolean ignoreFailure, 
+            @JsonProperty("install_first") boolean installFirst) {
         this.deploymentId = deploymentId;
         this.serviceTypeId = serviceTypeId;
         this.inputs = inputs;
         this.tenant = tenant;
         this.method = method;
+        this.reinstall_list = (reinstallList == null) ? new LinkedList<String>() : reinstallList;
+        this.skip_install = skipInstall;
+        this.skip_uninstall = skipUninstall;
+        this.skip_reinstall = skipReinstall;
+        this.force = force;
+        this.ignore_failure = ignoreFailure;
+        this.install_first = installFirst;
+    }
+
+    public DeploymentRequestObject(String deploymentId, String serviceTypeId, String method, 
+        Map<String, Object> inputs, String tenant) {
+        super();
+        this.deploymentId = deploymentId;
+        this.method = method;
+        this.serviceTypeId = serviceTypeId;
+        this.tenant = tenant;
+        this.inputs = inputs;
+        this.reinstall_list = null;
+        this.skip_install = true;
+        this.skip_uninstall = true;
+        this.skip_reinstall = true;
+        this.force = false;
+        this.ignore_failure = true;
+        this.install_first = false;
     }
 
     public String getDeploymentId() {
@@ -99,4 +148,32 @@ public class DeploymentRequestObject {
     public String getMethod() {
         return method;
     }
+
+    public Collection<String> getReinstall_list() {
+        return reinstall_list;
+    }
+
+    public boolean isSkip_install() {
+        return skip_install;
+    }
+
+    public boolean isSkip_uninstall() {
+        return skip_uninstall;
+    }
+
+    public boolean isSkip_reinstall() {
+        return skip_reinstall;
+    }
+
+    public boolean isForce() {
+        return force;
+    }
+
+    public boolean isIgnore_failure() {
+        return ignore_failure;
+    }
+
+    public boolean isInstall_first() {
+        return install_first;
+    }
 }
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/InventoryDeploymentRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/deploymenthandler/InventoryDeploymentRequest.java
deleted file mode 100644 (file)
index 173744a..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model.deploymenthandler;
-
-import java.util.Map;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-/**
- * Model for message used by the controller to create a DeploymentRequest for
- * the Deployment Handler API.
- * 
- * <pre>
-       {
-               "deploymentId" : "deploymentId",
-               "body" :
-                       { 
-                               "serviceTypeId" : "serviceTypeId",
-                               "inputs" :
-                                       {
-                                               "input1" : "parameter1"
-                                               "input2" : "parameter2"
-                                                               ...
-                                               "inputn" : "parametern"
-                                       }       
-                       }
-       }
- * </pre>
- */
-public final class InventoryDeploymentRequest {
-
-    /** Unique deployment identifier assigned by the API client. */
-    private final String deploymentId;
-
-    /**
-     * The service type identifier (a unique ID assigned by DCAE inventory) for the
-     * service to be deployed.
-     */
-    private final String serviceTypeId;
-
-    /**
-     * Object containing inputs needed by the service blueprint to create an
-     * instance of the service. Content of the object depends on the service being
-     * deployed.
-     */
-    private final Map<String, Object> inputs;
-
-    @JsonCreator
-    public InventoryDeploymentRequest(@JsonProperty("deploymentId") String deploymentId,
-            @JsonProperty("serviceTypeId") String serviceTypeId, @JsonProperty("inputs") Map<String, Object> inputs) {
-        this.deploymentId = deploymentId;
-        this.serviceTypeId = serviceTypeId;
-        this.inputs = inputs;
-    }
-
-    public String getDeploymentId() {
-        return this.deploymentId;
-    }
-
-    public String getServiceTypeId() {
-        return this.serviceTypeId;
-    }
-
-    public Map<String, Object> getInputs() {
-        return this.inputs;
-    }
-}
index 70f5fd5..184e0fb 100644 (file)
@@ -32,6 +32,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
 import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
 
 @JsonIgnoreProperties(ignoreUnknown = true)
@@ -39,6 +40,7 @@ public class Blueprint {
 
     private static final ObjectMapper YAML_MAPPER = new ObjectMapper(new YAMLFactory());
 
+
     static {
         YAML_MAPPER.registerModule(new Jdk8Module());
     }
index 3631623..dc1daa7 100644 (file)
@@ -57,7 +57,15 @@ public class Service {
     private Optional<Boolean> canDeploy;
     /** tenant name for this service */
     private String tenant;
-
+    /** install execution workflow status */
+    private String installStatus;
+    /** true if helm plugin is used */
+    public Boolean isHelm;
+    /** true if helm status is enabled */
+    public Boolean helmStatus;
+    /** Consul service health status */
+    private String healthStatus;
+    
     @JsonCreator
     public Service(@JsonProperty("serviceId") String serviceId, @JsonProperty("selfLink") Link selfLink,
             @JsonProperty("created") String created, @JsonProperty("modified") String modified,
@@ -165,4 +173,36 @@ public class Service {
      * public ServiceRef build() { return new ServiceRef(serviceId, created,
      * modified); } }
      */
+
+    public String getInstallStatus() {
+        return installStatus;
+    }
+
+    public void setInstallStatus(String installStatus) {
+        this.installStatus = installStatus;
+    }
+
+    public Boolean getIsHelm() {
+        return isHelm;
+    }
+
+    public void setIsHelm(Boolean isHelm) {
+        this.isHelm = isHelm;
+    }
+
+    public Boolean getHelmStatus() {
+        return helmStatus;
+    }
+
+    public void setHelmStatus(Boolean helmStatus) {
+        this.helmStatus = helmStatus;
+    }
+    
+    public String getHealthStatus() {
+       return this.healthStatus;
+    }
+    
+    public void setHealthStatus(String healthStatus) {
+       this.healthStatus = healthStatus;
+    }
 }
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceComponentRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceComponentRequest.java
deleted file mode 100644 (file)
index 123392b..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model.inventory;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class ServiceComponentRequest {
-
-    /** Component ID of the Service Component */
-    public String componentId;
-    /** Component Type of the Service Component */
-    public String componentType;
-    /**
-     * Specifies the name of the underlying source service responsible for this
-     * component
-     */
-    public String componentSource;
-    /**
-     * Used to determine if this component can be shared amongst different Services
-     */
-    public Integer shareable;
-
-    @JsonCreator
-    public ServiceComponentRequest(@JsonProperty("componentId") String componentId,
-            @JsonProperty("componentType") String componentType,
-            @JsonProperty("componentSource") String componentSource, @JsonProperty("shareable") Integer shareable) {
-        this.componentId = componentId;
-        this.componentType = componentType;
-        this.componentSource = componentSource;
-        this.shareable = shareable;
-    }
-
-    public static ServiceComponentRequest from(ServiceComponent sc) {
-        return new ServiceComponentRequest(sc.componentId, sc.componentType, sc.componentSource, sc.shareable);
-    }
-}
index f338d28..7b70e1c 100644 (file)
@@ -27,21 +27,25 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 public class ServiceRef {
 
     /** Service ID of the Service */
-    private final String serviceId;
+    public final String id;
     /** Creation date of the Service */
-    private final String created;
+    public final String created_at;
     /** Last modified date of the Service */
-    private final String modified;
-
+    public final String updated_at;
+    public final String tenant_name = "";
+    
     @JsonCreator
-    public ServiceRef(@JsonProperty("serviceId") String serviceId, @JsonProperty("created") String created,
-            @JsonProperty("modified") String modified) {
-        this.serviceId = serviceId;
-        this.created = created;
-        this.modified = modified;
+    public ServiceRef(
+        @JsonProperty("id") String serviceId, 
+        @JsonProperty("created_at") String created,
+        @JsonProperty("updated_at") String modified
+        ) {
+        this.id = serviceId;
+        this.created_at = created;
+        this.updated_at = modified;
 
     }
-
+/*
     public String getServiceId() {
         return serviceId;
     }
@@ -53,7 +57,7 @@ public class ServiceRef {
     public String getModified() {
         return modified;
     }
-
+*/
     /*
      * private ServiceRef ( String serviceId, String created, String modified) {
      * this.serviceId = serviceId; this.created = created; this.modified = modified;
index d9491d9..def0e0a 100644 (file)
@@ -23,6 +23,8 @@ package org.onap.ccsdk.dashboard.model.inventory;
 
 import java.util.Collection;
 
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
@@ -30,6 +32,7 @@ public class ServiceRefList {
     /** Number of Service objects */
     public final Integer totalCount;
     /** Collection containing all of the returned Service objects */
+    //public final Collection<CloudifyDeployedTenant> items;
     public final Collection<ServiceRef> items;
 
     @JsonCreator
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRequest.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceRequest.java
deleted file mode 100644 (file)
index 46b3351..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model.inventory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-public class ServiceRequest {
-
-    /** ID of the associated service type */
-    public String typeId;
-    /** Id of the associated VNF that this service is monitoring */
-    public String vnfId;
-    /** The type of the associated VNF that this service is monitoring */
-    public String vnfType;
-    /** Location identifier of the associated VNF that this service is monitoring */
-    public String vnfLocation;
-    /** Reference to a Cloudify deployment */
-    public String deploymentRef;
-    /**
-     * Collection of ServiceComponentRequest objects that this service is composed
-     * of
-     */
-    public Collection<ServiceComponentRequest> components;
-
-    @JsonCreator
-    public ServiceRequest(@JsonProperty("typeId") String typeId, @JsonProperty("vnfId") String vnfId,
-            @JsonProperty("vnfType") String vnfType, @JsonProperty("vnfLocation") String vnfLocation,
-            @JsonProperty("deploymentRef") String deploymentRef,
-            @JsonProperty("components") Collection<ServiceComponentRequest> components) {
-        this.typeId = typeId;
-        this.vnfId = vnfId;
-        this.vnfType = vnfType;
-        this.vnfLocation = vnfLocation;
-        this.deploymentRef = deploymentRef;
-        this.components = components;
-    }
-
-    public static ServiceRequest from(String typeId, Service service) {
-
-        // Convert the Collection<ServiceComponent> in service to
-        // Collection<ServiceComponentRequest> for serviceRequest
-        final Collection<ServiceComponent> serviceComponents = service.getComponents();
-        final Collection<ServiceComponentRequest> serviceComponentRequests = new ArrayList<ServiceComponentRequest>();
-
-        if (serviceComponents != null) {
-            for (ServiceComponent sc : serviceComponents) {
-                serviceComponentRequests.add(ServiceComponentRequest.from(sc));
-            }
-        }
-
-        return new ServiceRequest(typeId, service.getVnfId(), service.getVnfType(), service.getVnfLocation(),
-                service.getDeploymentRef(), serviceComponentRequests);
-    }
-}
index 4af4cb1..f1351fc 100644 (file)
@@ -237,8 +237,9 @@ public class ServiceType {
             this.blueprintInputs = bpObj.getInputs();
             this.blueprintDescription = bpObj.getDescription();
         } catch (BlueprintParseException e) {
-/*            throw new RuntimeException(
-                    "Error while parsing blueprint template for " + this.typeName + " " + this.typeVersion, e);*/
+            //this.blueprintDescription = "";
+            //throw new RuntimeException(
+                    //"Error while parsing blueprint template for " + this.typeName + " " + this.typeVersion, e);
         }
     }
 
index 8d98d9d..7b733ee 100644 (file)
@@ -33,9 +33,10 @@ public class ServiceTypeQueryParams {
     private final String asdcResourceId;
     private final String application;
     private final String component;
+    private final String owner;
 
     // Non-instantiable
-    private ServiceTypeQueryParams() {
+    private ServiceTypeQueryParams(org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary.Builder builder) {
         this.typeName = null;
         this.onlyLatest = null;
         this.onlyActive = null;
@@ -46,11 +47,12 @@ public class ServiceTypeQueryParams {
         this.asdcResourceId = null;
         this.application = null;
         this.component = null;
+        this.owner = null;
     }
 
     private ServiceTypeQueryParams(String typeName, Boolean onlyLatest, Boolean onlyActive, String vnfType,
             String serviceId, String serviceLocation, String asdcServiceId, String asdcResourceId, String application,
-            String component) {
+            String component, String owner) {
         this.typeName = typeName;
         this.onlyLatest = onlyLatest;
         this.onlyActive = onlyActive;
@@ -61,6 +63,7 @@ public class ServiceTypeQueryParams {
         this.asdcResourceId = asdcResourceId;
         this.application = application;
         this.component = component;
+        this.owner = owner;
     }
 
     public static class Builder {
@@ -74,7 +77,13 @@ public class ServiceTypeQueryParams {
         private String asdcResourceId;
         private String application;
         private String component;
+        private String owner;
 
+        public Builder owner(String owner) {
+            this.owner = owner;
+            return this;
+        }
+        
         public Builder typeName(String typeName) {
             this.typeName = typeName;
             return this;
@@ -115,9 +124,18 @@ public class ServiceTypeQueryParams {
             return this;
         }
 
+        public Builder application(String application) {
+            this.application = application;
+            return this;
+        }
+        
+        public Builder component(String component) {
+            this.component = component;
+            return this;
+        }
         public ServiceTypeQueryParams build() {
             return new ServiceTypeQueryParams(typeName, onlyLatest, onlyActive, vnfType, serviceId, serviceLocation,
-                    asdcServiceId, asdcResourceId, application, component);
+                    asdcServiceId, asdcResourceId, application, component, owner);
         }
     }
 
@@ -160,4 +178,8 @@ public class ServiceTypeQueryParams {
     public String getComponent() {
         return this.component;
     }
+    
+    public String getOwner() {
+        return this.owner;
+    }
 }
index 533571b..84efcb8 100644 (file)
@@ -100,6 +100,16 @@ public class ServiceTypeRequest {
         this.asdcResourceId = asdcResourceId;
         this.asdcServiceURL = asdcServiceURL;
     }
+    
+    public ServiceTypeRequest(String owner, String typeName, Integer typeVersion, String blueprintTemplate,
+        String application, String component) {
+        this.owner = owner;
+        this.typeName = typeName;
+        this.typeVersion = typeVersion;
+        this.blueprintTemplate = blueprintTemplate;
+        this.application = application;
+        this.component = component;
+    }
 
     public static ServiceTypeRequest from(ServiceType serviceType) {
         return new ServiceTypeRequest(serviceType.getOwner(), serviceType.getTypeName(), serviceType.getTypeVersion(),
@@ -107,7 +117,12 @@ public class ServiceTypeRequest {
                 serviceType.getServiceIds(), serviceType.getVnfTypes(), serviceType.getServiceLocations(),
                 serviceType.getAsdcServiceId(), serviceType.getAsdcResourceId(), serviceType.getAsdcServiceURL());
     }
-
+/*
+    public static ServiceTypeRequest from(ServiceType serviceType) {
+        return new ServiceTypeRequest(serviceType.getOwner(), serviceType.getTypeName(), serviceType.getTypeVersion(),
+                serviceType.getBlueprintTemplate(), serviceType.getApplication(), serviceType.getComponent());
+    }
+*/  
     public String getBlueprintTemplate() {
         return this.blueprintTemplate;
     }
index efcdf3b..3b2f541 100644 (file)
@@ -2,7 +2,7 @@
  * =============LICENSE_START=========================================================
  *
  * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
  * ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -17,7 +17,6 @@
  *  limitations under the License.
  * ============LICENSE_END=========================================================
  *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
  *******************************************************************************/
 package org.onap.ccsdk.dashboard.model.inventory;
 
@@ -28,11 +27,11 @@ public class ServiceTypeServiceMap {
 
     private final String serviceTypeId;
 
-    private final ServiceRefList serviceRefList;
+    private final Object serviceRefList;
 
     @JsonCreator
     public ServiceTypeServiceMap(@JsonProperty("serviceTypeId") String serviceTypeId,
-            @JsonProperty("created") ServiceRefList serviceRefList) {
+            @JsonProperty("serviceRefList") Object serviceRefList) {
         this.serviceTypeId = serviceTypeId;
         this.serviceRefList = serviceRefList;
     }
@@ -41,7 +40,7 @@ public class ServiceTypeServiceMap {
         return serviceTypeId;
     }
 
-    public ServiceRefList getServiceRefList() {
+    public Object getServiceRefList() {
         return serviceRefList;
     }
 }
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummary.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummary.java
new file mode 100644 (file)
index 0000000..877a8ed
--- /dev/null
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ *******************************************************************************/
+
+package org.onap.ccsdk.dashboard.model.inventory;
+
+import java.util.Optional;
+
+import org.apache.commons.lang3.StringUtils;
+import org.onap.ccsdk.dashboard.model.cloudify.ServiceRefCfyList;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * @author rp5662
+ *
+ */
+public class ServiceTypeSummary {
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "ServiceTypeSummary [owner=" + owner + ", typeName=" + typeName + ", typeVersion="
+            + typeVersion + ", component=" + component + ", typeId=" + typeId + ", created="
+            + created + "]";
+    }
+
+    /** Owner of the ServiceType */
+    private final String owner;
+
+    /** Name of the ServiceType */
+    private final String typeName;
+
+    /** Version number for this ServiceType */
+    private final Integer typeVersion;
+
+    /** controller application name */
+    private final String application;
+    
+    /** onboarding component name */
+    private final String component;
+    
+    /** Unique identifier for this ServiceType */
+    private final Optional<String> typeId;
+
+    /** Creation date of the ServiceType */
+    private final Optional<String> created;
+    
+    /** internal role based setting */
+    private Optional<Boolean> canDeploy;
+    
+    private ServiceRefCfyList deployments;
+    
+    private Optional<Boolean> expanded;
+    
+    @JsonCreator
+    public ServiceTypeSummary(
+        @JsonProperty("owner") String owner, 
+        @JsonProperty("typeName") String typeName,
+        @JsonProperty("typeVersion") Integer typeVersion,
+        @JsonProperty("application") String application, 
+        @JsonProperty("component") String component,
+        @JsonProperty("typeId") String typeId,
+        @JsonProperty("created") String created,
+        @JsonProperty("canDeploy") Boolean canDeploy) {
+
+        this.owner = owner;
+        this.typeName = typeName;
+        this.typeVersion = typeVersion;
+        this.application = application;
+        this.component = component;
+        this.typeId = Optional.ofNullable(typeId);
+        this.created = Optional.ofNullable(created);
+        this.canDeploy = Optional.of(false);
+        this.expanded = Optional.of(false);
+    }
+
+    private ServiceTypeSummary(Builder builder) {
+        this.typeName = builder.typeName;
+        this.owner = builder.owner;
+        this.typeVersion = builder.typeVersion;
+        this.typeId = builder.typeId;
+        this.application = builder.application;
+        this.component = builder.component;
+        this.created = builder.created;
+        this.canDeploy = builder.canDeploy;
+    }
+    
+    public static class Builder {
+        private String owner;
+        private String typeName;
+        private Integer typeVersion;
+        private String application;
+        private String component;
+        private Optional<String> typeId = Optional.empty();
+        private Optional<String> created = Optional.empty();
+        private Optional<Boolean> canDeploy = Optional.empty();
+        
+        public Builder owner(String owner) {
+            this.owner = owner;
+            return this;
+        }
+
+        public Builder typeName(String typeName) {
+            this.typeName = typeName;
+            return this;
+        }
+
+        public Builder typeVersion(Integer typeVersion) {
+            this.typeVersion = typeVersion;
+            return this;
+        }
+        
+        public Builder application(String application) {
+            this.application = application;
+            return this;
+        }
+        
+        public Builder component(String component) {
+            this.component = component;
+            return this;
+        }
+        public ServiceTypeSummary build() {
+            return new ServiceTypeSummary(this);
+        }
+    }
+    
+    public String getTypeName() {
+        return typeName;
+    }
+
+    public String getOwner() {
+        return owner;
+    }
+
+    public Integer getTypeVersion() {
+        return typeVersion;
+    }
+
+    public String getApplication() {
+        return application;
+    }
+
+    public String getComponent() {
+        return component;
+    }
+
+    public Optional<String> getTypeId() {
+        return typeId;
+    }
+
+    public Optional<String> getCreated() {
+        return created;
+    }
+
+    public Optional<Boolean> getCanDeploy() {
+        return canDeploy;
+    }
+
+    public void setCanDeploy(Optional<Boolean> canDeploy) {
+        this.canDeploy = canDeploy;
+    }    
+
+    public ServiceRefCfyList getDeployments() {
+        return deployments;
+    }
+
+    public void setDeployments(ServiceRefCfyList deployments) {
+        this.deployments = deployments;
+    }
+    
+    // Used for back end search, only searches the fields displayed in the front
+    // end.
+    public boolean contains(String searchString) {
+        if (StringUtils.containsIgnoreCase(this.getOwner(), searchString)
+                || StringUtils.containsIgnoreCase(this.getTypeId().get(), searchString)
+                || StringUtils.containsIgnoreCase(this.getTypeName(), searchString)
+                || StringUtils.containsIgnoreCase(Integer.toString(this.getTypeVersion()), searchString)
+                || StringUtils.containsIgnoreCase(this.getCreated().get(), searchString)
+                || StringUtils.containsIgnoreCase(this.getComponent(), searchString)
+                || StringUtils.containsIgnoreCase(this.getApplication(), searchString)) {
+            return true;
+        }
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((typeId == null) ? 0 : typeId.hashCode());
+        return result;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ServiceTypeSummary other = (ServiceTypeSummary) obj;
+        if (typeId == null) {
+            if (other.typeId != null)
+                return false;
+        } else if (!typeId.equals(other.typeId))
+            return false;
+        return true;
+    }
+
+}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummaryList.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/model/inventory/ServiceTypeSummaryList.java
new file mode 100644 (file)
index 0000000..149e75b
--- /dev/null
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.ccsdk.dashboard.model.inventory;
+
+import java.util.Collection;
+
+import org.onap.ccsdk.dashboard.model.ECTransportModel;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ServiceTypeSummaryList extends ECTransportModel {
+
+    /** Number of ServiceType objects */
+    public final Integer totalCount;
+    /** Collection containing all of the returned ServiceType objects */
+    public final Collection<ServiceTypeSummary> items;
+    /** Links to the previous and next page of items */
+    public final PaginationLinks paginationLinks;
+
+    @JsonCreator
+    public ServiceTypeSummaryList(
+        @JsonProperty("items") Collection<ServiceTypeSummary> items,
+        @JsonProperty("totalCount") Integer totalCount,
+        @JsonProperty("links") PaginationLinks paginationLinks) {
+        this.items = items;
+        this.totalCount = totalCount;
+        this.paginationLinks = paginationLinks;
+    }
+
+    /** InlineResponse200Links */
+    public static final class PaginationLinks {
+        public final Link previousLink;
+        public final Link nextLink;
+
+        @JsonCreator
+        public PaginationLinks(@JsonProperty("previousLink") Link previousLink,
+                @JsonProperty("nextLink") Link nextLink) {
+            this.previousLink = previousLink;
+            this.nextLink = nextLink;
+        }
+    }
+}
index 1ffab54..04a084e 100644 (file)
  *******************************************************************************/
 package org.onap.ccsdk.dashboard.rest;
 
+import java.util.List;
 import java.util.Map;
 
-import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateResponse;
-import org.onap.ccsdk.dashboard.model.CloudifyEventList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecution;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceList;
-import org.onap.ccsdk.dashboard.model.CloudifyTenantList;
+import javax.servlet.http.HttpServletRequest;
+
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprintList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentExt;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentHelm;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPluginList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret;
 
 /**
  * @author rp5662
@@ -51,7 +57,7 @@ public interface CloudifyClient {
     /**
      * Gets the list of Cloudify tenants.
      * 
-     * @return CloudifyBlueprintList
+     * @return CloudifyTenantList
      */
     public CloudifyTenantList getTenants();
 
@@ -84,13 +90,6 @@ public interface CloudifyClient {
      */
     public CloudifyNodeInstanceIdList getNodeInstanceId(String deploymentId, String nodeId, String tenant);
 
-    /**
-     * Gets all the deployments with include filters for tenant name
-     * 
-     * @return List of CloudifyDeployedTenant objects
-     */
-    public CloudifyDeployedTenantList getTenantInfoFromDeploy(String tenant);
-
     /**
      * Get the node-instance-id.
      * 
@@ -101,14 +100,6 @@ public interface CloudifyClient {
      */
     public CloudifyNodeInstanceIdList getNodeInstanceId(String id, String tenant);
 
-    /**
-     * Initiate a deployment update in cloudify
-     * 
-     * @param execution
-     * @return
-     */
-    public CloudifyDeploymentUpdateResponse updateDeployment(CloudifyDeploymentUpdateRequest execution);
-
     /**
      * Query execution information for a deployment ID passed as input
      * 
@@ -167,7 +158,21 @@ public interface CloudifyClient {
      * Query deployments from cloudify
      * 
      */
-    public CloudifyDeploymentList getDeployments();
+    public CloudifyDeploymentList getDeployments(String tenant, int pageSize, int pageOffset);
+    
+    /**
+     * Query deployments from cloudify and filter based
+     * on given input key and value
+     * At the moment only supports key "contains" not "equals"
+     * For value it supports only "equals" not "contains"
+     * @param inputKey
+     * @param inputValue
+     * @param returnFullDeployment If true, returns full deployment obj, otherwise only some attributes
+     * @return
+     */
+    public List<CloudifyDeployment> getDeploymentsByInputFilter(String inputKey, String inputValue) throws Exception;
+    
+    public List<CloudifyDeployment> getDeploymentsWithFilter(HttpServletRequest request, String filter) throws Exception;
 
     /**
      * Query a blueprint object matching the blueprint ID in cloudify
@@ -186,4 +191,70 @@ public interface CloudifyClient {
      * @return
      */
     public CloudifyDeploymentList getDeploymentInputs(String id, String tenant);
+    
+    /**
+     * Query a cloudify secret under a tenant scope
+     * 
+     * @param secretName
+     * @param tenant
+     * @return
+     */
+    public CloudifySecret getSecret(String secretName, String tenant);
+
+    /**
+     * Query install workflow execution summary for a deployment ID
+     * 
+     * @param deploymentId
+     * @param tenant
+     * @return
+     */
+    public CloudifyExecutionList getInstallExecutionSummary(String deploymentId, String tenant);
+    
+    /**
+     * 
+     * Delete Blueprint
+     * 
+     * @param blueprint ID
+     */
+    public void deleteBlueprint(String bpName, String tenant);
+    /**
+     * 
+     * Query deployment node instances
+     * 
+     * @param deploymentId
+     * @param tenant
+     * @return
+     */
+    public CloudifyNodeInstanceIdList getNodeInstances(String deploymentId, String tenant);
+
+    public List<CloudifyDeployment> getDeployments(String tenant, int pageSize, int pageOffset,
+        boolean recurse);
+
+    public List<CloudifyDeployment> getDeployments(String tenant, int pageSize, int pageOffset,
+        boolean recurse, boolean cache);
+    
+    public byte[] viewBlueprint(String tenant, String id);
+
+    public void cacheDeployments();
+
+    public CloudifyDeployment getDeploymentResource(final String id, final String tenant);
+
+    public List<CloudifyDeployment> getDeploymentsWithFilter(HttpServletRequest request) throws Exception;
+
+    public CloudifyNodeInstanceList getNodeInstanceDetails(String deploymentId, String tenant);
+    
+    public List<CloudifyDeployedTenant> getDeploymentForBlueprint(final String bpId);
+
+    public List<CloudifyDeploymentExt> updateWorkflowStatus(List<CloudifyDeployment> itemList);
+    
+    public List<CloudifyDeploymentHelm> updateHelmInfo(List<CloudifyDeployment> itemList);
+
+    public List<String> getDeploymentNamesWithFilter(HttpServletRequest request)
+        throws Exception;
+    
+    public CloudifyPluginList getPlugins();
+
+    public CloudifyExecutionList getExecutionsSummaryPerTenant(String tenant);
+    
+    public CloudifyExecution getExecutionIdSummary(final String id, final String tenant);
 }
index 28bd87c..0e64ef0 100644 (file)
@@ -23,32 +23,53 @@ package org.onap.ccsdk.dashboard.rest;
 
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
-
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
 import javax.annotation.PostConstruct;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
 
 import org.json.JSONObject;
-import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateResponse;
-import org.onap.ccsdk.dashboard.model.CloudifyEventList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecution;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeIdList;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceList;
-import org.onap.ccsdk.dashboard.model.CloudifyTenantList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprint;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprintList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenantList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentExt;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentHelm;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeIdList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPluginList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenant;
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.onap.portalsdk.core.objectcache.AbstractCacheManager;
+import org.onap.portalsdk.core.web.support.AppUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.scheduling.annotation.Scheduled;
 
 @org.springframework.stereotype.Service
 public class CloudifyRestClientImpl extends RestClientBase implements CloudifyClient {
@@ -64,19 +85,35 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl
     private static final String NODE_INSTANCES = "node-instances";
     private static final String UPDATE_DEPLOYMENT = "update-deployment";
     private static final String EVENTS = "events";
-    private static final String TENANT = "tenant_name";
+    private static final String SECRETS = "secrets";
+    private static final String SERVICE_ID = "service-list";
+    private static final String PLUGINS = "plugins";
+    
+    /**
+     * For caching data 
+     */
+    private AbstractCacheManager cacheManager;   
+    
+    @Autowired
+    public void setCacheManager(AbstractCacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+    }
 
+    public AbstractCacheManager getCacheManager() {
+        return cacheManager;
+    }
+    
     @PostConstruct
     public void init() {
-        String webapiUrl = DashboardProperties.getControllerProperty("dev",
-            DashboardProperties.CONTROLLER_SUBKEY_URL);
+        String webapiUrl = DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_CLOUDIFY_URL);
         if (webapiUrl == null) {
             throw new IllegalArgumentException("Null URL not permitted");
         }
-        String user = DashboardProperties.getControllerProperty("dev",
-            DashboardProperties.CONTROLLER_SUBKEY_USERNAME);
-        String pass = DashboardProperties.getControllerProperty("dev",
-            DashboardProperties.CONTROLLER_SUBKEY_PASS);
+        String user = DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_CLOUDIFY_USERNAME);
+        String pass = DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_CLOUDIFY_PASS);
         URL url = null;
         try {
             url = new URL(webapiUrl);
@@ -90,6 +127,207 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl
         }
     }
 
+    @SuppressWarnings("unchecked")
+    public List<CloudifyDeploymentHelm> updateHelmInfo(List<CloudifyDeployment> itemList) {
+        boolean isHelm = false;
+        boolean helmStatus = false;
+        List<CloudifyDeploymentHelm> result = new ArrayList<>();
+        for (CloudifyDeployment srvc : (List<CloudifyDeployment>) itemList) {            
+            try {
+                isHelm = false;
+                helmStatus = false;
+                CloudifyBlueprintList bpList =
+                    this.getBlueprint(srvc.blueprint_id, srvc.tenant_name);
+                Map<String, Object> bpPlan = bpList.items.get(0).plan;
+                Map<String, String> workflows = (Map<String, String>) bpPlan.get("workflows");
+                Map<String, String> pluginInfo =
+                    ((List<Map<String, String>>) bpPlan.get("deployment_plugins_to_install"))
+                        .get(0);
+                if (pluginInfo.get("name").equals("helm-plugin")) {
+                    isHelm = true;
+                }
+                if (workflows.containsKey("status")) {
+                    helmStatus = true;
+                }
+                CloudifyDeploymentHelm cfyDeplHelm = 
+                    new CloudifyDeploymentHelm(srvc.id, isHelm, helmStatus);
+                result.add(cfyDeplHelm);
+            } catch (Exception e) {
+                logger.error(EELFLoggerDelegate.errorLogger, "getBlueprint failed");
+                CloudifyDeploymentHelm cfyDeplHelm = 
+                    new CloudifyDeploymentHelm(srvc.id, false, false);
+                result.add(cfyDeplHelm);
+                continue;
+            }
+        }
+        return result;
+    }
+    
+    public List<CloudifyDeploymentExt> updateWorkflowStatus(List<CloudifyDeployment> itemList) {
+        List<CloudifyDeploymentExt> result = new ArrayList<>();
+        for (CloudifyDeployment srvc : (List<CloudifyDeployment>) itemList) {
+            try {
+                // find deployment execution info per item
+                CloudifyExecutionList execResults =
+                    this.getExecutionsSummary(srvc.id, srvc.tenant_name);
+                if (execResults.items != null && !execResults.items.isEmpty()) {
+                    CloudifyDeploymentExt cfyDeplExt = 
+                        new CloudifyDeploymentExt(srvc.id, 
+                            srvc.blueprint_id, srvc.tenant_name);
+                    cfyDeplExt.lastExecution = 
+                        execResults.items.get(0); 
+                    result.add(cfyDeplExt);
+                }
+            } catch (Exception e) {
+                logger.error(EELFLoggerDelegate.errorLogger, "getExecutionsSummary failed");
+                srvc.lastExecution = null;
+                continue;
+            }
+        }
+        return result;
+    }
+    
+    public List<CloudifyDeployedTenant> getDeploymentForBlueprint(final String bpId) {
+        String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS },
+            new String[] {  "blueprint_id", bpId, "_all_tenants", "true", "_include", "id,created_at,updated_at,tenant_name"});
+        logger.debug(EELFLoggerDelegate.debugLogger, "getDeploymentForBlueprint begin: url {}", url);
+        ResponseEntity<CloudifyDeployedTenantList> response = restTemplate.exchange(url, HttpMethod.GET, null,
+                new ParameterizedTypeReference<CloudifyDeployedTenantList>() {
+                });
+        return response.getBody().items;
+    }
+    
+    public CloudifyDeployment getDeploymentResource(final String id, final String tenant) {
+        String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, 
+            new String[] {  "id", id, "_include", "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name",
+            "_sort","-updated_at", "_sort", "-created_at"});
+        logger.debug(EELFLoggerDelegate.debugLogger, "getDeploymentResource begin: url {}", url);
+        HttpEntity<String> entity = getTenantHeader(tenant);
+        ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, entity,
+                new ParameterizedTypeReference<CloudifyDeploymentList>() {
+                });
+        return response.getBody().items.get(0);
+    }
+    
+    @Scheduled(fixedRate=86400000, initialDelay=15000)
+    public void cacheTenants() {
+        logger.debug(EELFLoggerDelegate.debugLogger, "cacheTenants begin");
+        CloudifyTenantList tenantsList = this.getTenants();
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        lock.writeLock().lock();
+        getCacheManager().putObject(TENANTS, tenantsList.items);
+        lock.writeLock().unlock();
+        logger.debug(EELFLoggerDelegate.debugLogger, "cacheTenants end");
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Scheduled(fixedDelay=3600000, initialDelay=360000)
+    public void cacheDeploymentExecInfo() {
+        logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeploymentExecInfo begin");
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        lock.readLock().lock();
+        List<CloudifyTenant> tenantItems = 
+            (List<CloudifyTenant>) getCacheManager().getObject(TENANTS);
+        lock.readLock().unlock();
+        String cfyTen = "";
+        if (tenantItems != null) {
+            for (CloudifyTenant item : tenantItems) {
+                cfyTen = item.name;
+                lock.readLock().lock();
+                List<CloudifyDeployment> cfyDeplList = 
+                    (List<CloudifyDeployment>)getCacheManager().
+                    getObject(SERVICE_ID + ":" + cfyTen);
+                lock.readLock().unlock(); 
+                if (cfyDeplList != null) {
+                    List<CloudifyDeploymentExt> cfyDeplExecList = 
+                        this.updateWorkflowStatus(cfyDeplList);
+                    lock.writeLock().lock();
+                        getCacheManager().putObject(SERVICE_ID + ":" + cfyTen + ":ext", cfyDeplExecList);
+                    lock.writeLock().unlock();
+                }
+            }
+        }
+        logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeploymentExecInfo end");
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Scheduled(fixedDelay=3900000, initialDelay=600000)
+    public void cacheDeploymentHelmInfo() {
+        logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeploymentHelmInfo begin");
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        lock.readLock().lock();
+        List<CloudifyTenant> tenantItems = 
+            (List<CloudifyTenant>) getCacheManager().getObject(TENANTS);
+        lock.readLock().unlock();
+        String cfyTen = "";
+        if (tenantItems != null) {
+            for (CloudifyTenant item : tenantItems) {
+                cfyTen = item.name;
+                lock.readLock().lock();
+                List<CloudifyDeployment> cfyDeplList = 
+                    (List<CloudifyDeployment>)getCacheManager().
+                    getObject(SERVICE_ID + ":" + cfyTen);
+                lock.readLock().unlock();
+                if (cfyDeplList != null) {
+                    List<CloudifyDeploymentHelm> cfyDeplHelmList = 
+                        this.updateHelmInfo(cfyDeplList);
+                    lock.writeLock().lock();
+                    getCacheManager().putObject(SERVICE_ID + ":" + cfyTen + ":helm", cfyDeplHelmList);
+                    lock.writeLock().unlock();                 
+                }
+            }
+        }
+        logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeploymentHelmInfo end");
+    }
+    
+    @Scheduled(fixedDelay=300000, initialDelay=90000)
+    public void cacheDeployments() {
+        logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeployments begin");
+        int pageSize = 500;
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        lock.readLock().lock();
+        List<CloudifyTenant> tenantItems = 
+            (List<CloudifyTenant>) getCacheManager().getObject(TENANTS);
+        lock.readLock().unlock();
+        String cfyTen = "default_tenant";
+        if (tenantItems != null) {
+            for (CloudifyTenant item : tenantItems) {
+                cfyTen = item.name;
+                String url = buildUrl(new String[] {baseUrl, DEPLOYMENTS},
+                    new String[] {"_include",
+                        "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name",
+                        "_sort", "-updated_at", "_sort", "-created_at", "_size",
+                        new Integer(pageSize).toString(), "_offset", new Integer(0).toString()});
+                logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeployments begin: url {}", url);
+                HttpEntity<String> entity = getTenantHeader(cfyTen);
+                ResponseEntity<CloudifyDeploymentList> response =
+                    restTemplate.exchange(url, HttpMethod.GET, entity,
+                        new ParameterizedTypeReference<CloudifyDeploymentList>() {});
+                List<CloudifyDeployment> cfyDeplList = new ArrayList<CloudifyDeployment>();
+                cfyDeplList.addAll(response.getBody().items);
+                int totalItems = (int) response.getBody().metadata.pagination.total;
+                int deplPgOffset = 0;
+                deplPgOffset += pageSize;
+                while (deplPgOffset < totalItems) {
+                    url = buildUrl(new String[] {baseUrl, DEPLOYMENTS}, new String[] {
+                        "_include",
+                        "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name",
+                        "_sort", "-updated_at", "_sort", "-created_at", "_size",
+                        new Integer(pageSize).toString(), "_offset",
+                        new Integer(deplPgOffset).toString()});
+                    response = restTemplate.exchange(url, HttpMethod.GET, entity,
+                        new ParameterizedTypeReference<CloudifyDeploymentList>() {});
+                    deplPgOffset += pageSize;
+                    cfyDeplList.addAll(response.getBody().items);
+                }
+                lock.writeLock().lock();
+                getCacheManager().putObject(SERVICE_ID + ":" + cfyTen, cfyDeplList);
+                lock.writeLock().unlock();
+            }
+        }
+        logger.debug(EELFLoggerDelegate.debugLogger, "cacheDeployments done putting deployment data");
+    }
+
     @Override
     public CloudifyTenantList getTenants() {
         String url = buildUrl(new String[] { baseUrl, TENANTS }, null);
@@ -123,6 +361,30 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl
         return response.getBody();
     }
 
+    @Override
+    public CloudifyNodeInstanceList getNodeInstanceDetails(String deploymentId, String tenant) {
+        String url = buildUrl(new String[] { baseUrl, NODE_INSTANCES },
+                new String[] { "deployment_id", deploymentId});
+        logger.debug(EELFLoggerDelegate.debugLogger, "getNodeInstanceDetails: url {}", url);
+        HttpEntity<String> entity = getTenantHeader(tenant);
+        ResponseEntity<CloudifyNodeInstanceList> response = restTemplate.exchange(url, HttpMethod.GET, entity,
+                new ParameterizedTypeReference<CloudifyNodeInstanceList>() {
+                });
+        return response.getBody();
+    }
+    
+    @Override
+    public CloudifyNodeInstanceIdList getNodeInstances(String deploymentId, String tenant) {
+        String url = buildUrl(new String[] { baseUrl, NODE_INSTANCES },
+                new String[] { "deployment_id", deploymentId, "_include", "id" });
+        logger.debug(EELFLoggerDelegate.debugLogger, "getNodeInstanceId: url {}", url);
+        HttpEntity<String> entity = getTenantHeader(tenant);
+        ResponseEntity<CloudifyNodeInstanceIdList> response = restTemplate.exchange(url, HttpMethod.GET, entity,
+                new ParameterizedTypeReference<CloudifyNodeInstanceIdList>() {
+                });
+        return response.getBody();
+    }
+
     @Override
     public CloudifyNodeInstanceList getNodeInstanceVersion(String deploymentId, String nodeId, String tenant) {
         String url = buildUrl(new String[] { baseUrl, NODE_INSTANCES },
@@ -164,21 +426,20 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl
     }
 
     @Override
-    public CloudifyDeployedTenantList getTenantInfoFromDeploy(String tenant) {
-        String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS },
-                new String[] { "_include", "id,blueprint_id,tenant_name" });
-        logger.debug(EELFLoggerDelegate.debugLogger, "getTenantInfoFromDeploy: url {}", url);
+    public CloudifyExecutionList getExecutions(final String deploymentId, final String tenant) {
+        String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, new String[] { "deployment_id", deploymentId });
+        logger.debug(EELFLoggerDelegate.debugLogger, "getExecutions: url {}", url);
         HttpEntity<String> entity = getTenantHeader(tenant);
-
-        ResponseEntity<CloudifyDeployedTenantList> response = restTemplate.exchange(url, HttpMethod.GET, entity,
-                new ParameterizedTypeReference<CloudifyDeployedTenantList>() {
+        ResponseEntity<CloudifyExecutionList> response = restTemplate.exchange(url, HttpMethod.GET, entity,
+                new ParameterizedTypeReference<CloudifyExecutionList>() {
                 });
         return response.getBody();
     }
 
     @Override
-    public CloudifyExecutionList getExecutions(final String deploymentId, final String tenant) {
-        String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, new String[] { "deployment_id", deploymentId });
+    public CloudifyExecutionList getExecutionsSummary(final String deploymentId, final String tenant) {
+        String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, new String[] { "deployment_id", deploymentId,
+                "_include", "deployment_id,id,status,workflow_id,tenant_name,created_at,ended_at", "_sort", "-created_at" });
         logger.debug(EELFLoggerDelegate.debugLogger, "getExecutions: url {}", url);
         HttpEntity<String> entity = getTenantHeader(tenant);
         ResponseEntity<CloudifyExecutionList> response = restTemplate.exchange(url, HttpMethod.GET, entity,
@@ -188,9 +449,32 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl
     }
 
     @Override
-    public CloudifyExecutionList getExecutionsSummary(final String deploymentId, final String tenant) {
+    public CloudifyExecutionList getExecutionsSummaryPerTenant(final String tenant) {
+        String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, new String[] {
+                "_include","deployment_id,id,status,workflow_id,tenant_name,created_at,ended_at", "_sort", "-created_at" });
+        logger.debug(EELFLoggerDelegate.debugLogger, "getExecutionsSummaryPerTenant: url {}", url);
+        HttpEntity<String> entity = getTenantHeader(tenant);
+        ResponseEntity<CloudifyExecutionList> response = restTemplate.exchange(url, HttpMethod.GET, entity,
+                new ParameterizedTypeReference<CloudifyExecutionList>() {
+                });
+        return response.getBody();
+    }
+
+    public CloudifyExecution getExecutionIdSummary(final String id, final String tenant) {
+        String url = buildUrl(new String[] { baseUrl, EXECUTIONS, id }, new String[] {
+            "_include","deployment_id,id,status,workflow_id,tenant_name,created_at,ended_at", "_sort", "-created_at" });
+        logger.debug(EELFLoggerDelegate.debugLogger, "getExecutionIdSummary: url {}", url);
+        HttpEntity<String> entity = getTenantHeader(tenant);
+        ResponseEntity<CloudifyExecution> response = restTemplate.exchange(url, HttpMethod.GET, entity,
+                new ParameterizedTypeReference<CloudifyExecution>() {
+                });
+        return response.getBody();
+    }
+    
+    @Override
+    public CloudifyExecutionList getInstallExecutionSummary(final String deploymentId, final String tenant) {
         String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, new String[] { "deployment_id", deploymentId,
-                "_include", "deployment_id,id,status,workflow_id,tenant_name,created_at" });
+                "workflow_id", "install", "_include", "deployment_id,id,status,workflow_id,tenant_name,created_at" });
         logger.debug(EELFLoggerDelegate.debugLogger, "getExecutions: url {}", url);
         HttpEntity<String> entity = getTenantHeader(tenant);
         ResponseEntity<CloudifyExecutionList> response = restTemplate.exchange(url, HttpMethod.GET, entity,
@@ -198,7 +482,7 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl
                 });
         return response.getBody();
     }
-
+    
     @Override
     public CloudifyExecution startExecution(CloudifyExecutionRequest execution) {
         String url = buildUrl(new String[] { baseUrl, EXECUTIONS }, null);
@@ -210,13 +494,6 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl
         return restTemplate.postForObject(url, entity, CloudifyExecution.class);
     }
 
-    @Override
-    public CloudifyDeploymentUpdateResponse updateDeployment(CloudifyDeploymentUpdateRequest execution) {
-        String url = buildUrl(new String[] { baseUrl, UPDATE_DEPLOYMENT }, null);
-        logger.debug(EELFLoggerDelegate.debugLogger, "updateDeployment: url {}", url);
-        return restTemplate.postForObject(url, execution, CloudifyDeploymentUpdateResponse.class);
-    }
-
     @Override
     public CloudifyExecution cancelExecution(final String executionId, Map<String, String> parameters,
             final String tenant) {
@@ -246,18 +523,516 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl
     }
 
     @Override
-    public CloudifyDeploymentList getDeployments() {
-        String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, null);
+    public byte[] viewBlueprint(String tenant, final String id) {
+        String url = buildUrl(new String[] { baseUrl, BLUEPRINTS, id, "archive" }, null);
+        logger.debug(EELFLoggerDelegate.debugLogger, "viewBlueprint: url {}", url);
+        HttpEntity<String> entity = getTenantHeader(tenant);
+        ResponseEntity<byte[]> response = 
+            restTemplate.exchange(url, HttpMethod.GET, entity, byte[].class);
+        if (response.getStatusCode() == HttpStatus.OK) {
+            return response.getBody();
+        }
+        return null;
+    }
+    
+    @Override
+    public List<CloudifyDeployment> getDeployments(String tenant, int pageSize, int pageOffset, boolean recurse) {        
+        return this.getDeployments(tenant, pageSize, pageOffset, true, true);
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<CloudifyDeployment> getDeployments(String tenant, int pageSize, int pageOffset, boolean recurse, boolean cache) {
+        List<CloudifyDeployment> cfyDeplList = null;
+        if (cache) {
+            cfyDeplList = 
+                (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + tenant);
+        }
+        if (cfyDeplList == null || cfyDeplList.isEmpty()) {
+            String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, 
+                new String[] {  "_include", "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name",
+                "_sort","-updated_at", "_sort", "-created_at",
+                "_size", new Integer(pageSize).toString(), 
+                "_offset" , new Integer(pageOffset).toString()});
+            logger.debug(EELFLoggerDelegate.debugLogger, "getDeployments: url {}", url);
+            HttpEntity<String> entity = getTenantHeader(tenant);
+            ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, entity,
+                    new ParameterizedTypeReference<CloudifyDeploymentList>() {
+                    });
+            cfyDeplList = new ArrayList<CloudifyDeployment>();
+            cfyDeplList.addAll(response.getBody().items);
+            if (recurse) {
+                int totalItems = (int)response.getBody().metadata.pagination.total;
+                int deplPgOffset = 0;
+                deplPgOffset += pageSize;
+                while (deplPgOffset < totalItems) {
+                    url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, 
+                        new String[] {  "_include", "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name",
+                        "_sort","-updated_at", "_sort", "-created_at",
+                        "_size", new Integer(pageSize).toString(), 
+                        "_offset" , new Integer(deplPgOffset).toString()});
+                    response = restTemplate.exchange(url, HttpMethod.GET, entity,
+                        new ParameterizedTypeReference<CloudifyDeploymentList>() {
+                        });
+                    deplPgOffset += pageSize;
+                    cfyDeplList.addAll(response.getBody().items);
+                }
+            }
+        }
+        return cfyDeplList;
+    }
+    
+    public CloudifyDeploymentList getDeployments(String tenant, int pageSize, int pageOffset) {
+        String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, 
+            new String[] {  "_include", "id,blueprint_id,created_at,updated_at,created_by,description",
+            "_sort","-updated_at", "_sort", "-created_at",
+            "_size", new Integer(pageSize).toString(), 
+            "_offset" , new Integer(pageOffset).toString()});
         logger.debug(EELFLoggerDelegate.debugLogger, "getDeployments: url {}", url);
-        ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, null,
+        HttpEntity<String> entity = getTenantHeader(tenant);
+        ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, entity,
                 new ParameterizedTypeReference<CloudifyDeploymentList>() {
                 });
+
         return response.getBody();
     }
+    
+    @Override
+    public List<CloudifyDeployment> getDeploymentsByInputFilter(String inputKey, String inputValue) throws Exception {
+       JSONObject inputObject = new JSONObject()
+                               .put("inputKey", inputKey)
+                               .put("inputValue", inputValue);
+       String filter = new JSONObject()
+                                               .put("input", inputObject)
+                                               .toString();
+       return getDeploymentsWithFilter(null, filter);
+    }
+  
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<String> getDeploymentNamesWithFilter(HttpServletRequest request) 
+        throws Exception {
+        List<CloudifyDeployment> itemList = this.getDeploymentsWithFilter(request);
+        Set<String> svcIdList = new HashSet<String>();
+        if (itemList != null) {
+            svcIdList = 
+            (Set) itemList.stream().map(x -> ((CloudifyDeployment)x).id).collect(Collectors.toSet());
+        }
+        List<String> response = new ArrayList<String>();
+        response.addAll(svcIdList);
+        return response;
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Override
+    public List<CloudifyDeployment> getDeploymentsWithFilter(HttpServletRequest request) throws Exception {       
+        String filters = request.getParameter("filters");
+        List<CloudifyDeployment> deployments = new ArrayList<CloudifyDeployment>();
+        if (filters != null) {           
+            deployments = getDeploymentsWithFilter(request, filters);
+        } else {
+            List<CloudifyTenant> selectedTenants = new ArrayList<CloudifyTenant>();
+            selectedTenants = getTenants().items;
+            List<CloudifyDeployment> itemList = null;
+            for (CloudifyTenant tenant : selectedTenants) {
+                itemList = this.getDeployments(tenant.name, 500, 0, true);
+                deployments.addAll(itemList);
+            }
+            // apply user role based auth 
+            Set<String> userApps = null;
+            Set<String> userRoleSet = null;            
+            try {
+                HttpSession session = AppUtils.getSession(request);
+                userApps = (Set<String>) session.getAttribute("authComponents");
+                userRoleSet = (Set<String>) session.getAttribute("user_roles");
+            } catch (Exception e) {
+                // requester is REST API
+                userRoleSet = (Set<String>)request.getAttribute("userRoles");
+                userApps = (Set<String>) request.getAttribute("userApps");
+            }
+            
+            if (userApps == null) {
+                userApps = new TreeSet<String>();
+            }
+            
+            if (userRoleSet == null) {
+                userRoleSet = new TreeSet<String>();
+            }
+            
+            Predicate<String> adminPred =
+                p -> p.contains("System_Administrator") || p.contains("Write_Access");
+
+            Predicate<String> ecompSuperPred =
+                p -> p.contains("ECOMPC_WRITE") || p.contains("ECOMPC_READ");
+             
+            if (userRoleSet.size() > 0) {
+                if (userRoleSet.stream().noneMatch(adminPred)) {
+                    List<String> myApps = new ArrayList(userApps);
+                    if (userRoleSet.stream().noneMatch(ecompSuperPred)) {
+                        deployments = (List<CloudifyDeployment>) deployments.stream().filter(s -> myApps.stream()
+                            .anyMatch(roleFilter -> ((CloudifyDeployment)s).id.toLowerCase().startsWith(roleFilter)))
+                            .collect(Collectors.toList()); 
+                    } else {
+                        Predicate<CloudifyDeployment> appFilter = 
+                            p -> p.id.toLowerCase().indexOf("dcae") == -1 || p.id.toLowerCase().indexOf("d2a") == -1;
+                        deployments = (List<CloudifyDeployment>) deployments.stream().filter(appFilter)
+                            .collect(Collectors.toList());
+                    }
+                }
+            }
+        }
+        return deployments;
+    }
+    
+    @Override
+    public List<CloudifyDeployment> getDeploymentsWithFilter(HttpServletRequest request, String filter) 
+        throws Exception {
+       String url = "";
+       JSONObject filterJson = new JSONObject(filter);
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        
+       //---------Handle Tenant filter---------//
+       List<CloudifyTenant> selectedTenants = new ArrayList<CloudifyTenant>();
+       if (filterJson.has("tenant")) {
+               String tenantFilterString = "";
+               Object tenantObject = filterJson.get("tenant");
+
+               //Check for logic operators
+               if (tenantObject instanceof JSONObject) { 
+                       JSONObject tenantJsonObject = filterJson.getJSONObject("tenant");
+                       if (tenantJsonObject.has("$not")) {
+                               tenantFilterString = tenantJsonObject.getString("$not");
+                               selectedTenants = tenantFilter(tenantFilterString, true);
+                       }
+                       else {
+                               throw new Exception("ERROR: Not a valid logic operator");
+                       }
+               }
+               else if (tenantObject instanceof String) {
+                       tenantFilterString = filterJson.getString("tenant");
+                       selectedTenants = tenantFilter(tenantFilterString, false);
+               }
+       }
+       else {
+               selectedTenants = getTenants().items;
+       }               
+       //---------Get Deployments based on tenants selected---------//
+       List<CloudifyDeployment> deployments = new ArrayList<CloudifyDeployment>();
+       List<CloudifyDeployment> itemList = null;
+        HttpEntity<String> entity;
+        String tenantFilterStr = "";      
+        int pageSize = 500;
+        
+        //---------Handle the _include filter---------//
+        String include = filterJson.has("_include") ? filterJson.getString("_include") : null;       
+        for (CloudifyTenant tenant : selectedTenants) {
+                tenantFilterStr = tenant.name;
+                lock.readLock().lock();
+                itemList = 
+                    (List<CloudifyDeployment>)getCacheManager().
+                    getObject("service-list" + ":" + tenantFilterStr);
+                lock.readLock().unlock();
+                
+                if (itemList == null || include != null) {
+                    if (include == null || include.isEmpty()) {
+                        include = "id,blueprint_id,created_at,updated_at,created_by,description,tenant_name";
+                    }
+                    url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, new String[] {"_include", 
+                        include,"_sort", "-updated_at", "_sort", "-created_at", "_size",
+                        new Integer(pageSize).toString(), "_offset", new Integer(0).toString()});
+
+                        logger.debug(EELFLoggerDelegate.debugLogger, "getDeployments: url {}", url);
+                        
+                        entity = getTenantHeader(tenant.name);
+                        ResponseEntity<CloudifyDeploymentList> response = 
+                            restTemplate.exchange(url, HttpMethod.GET, entity,
+                                new ParameterizedTypeReference<CloudifyDeploymentList>() {
+                                });
+                        deployments.addAll(response.getBody().items);
+                        int totalItems = (int) response.getBody().metadata.pagination.total;
+                        int deplPgOffset = 0;
+                        deplPgOffset += pageSize;
+                        while (deplPgOffset < totalItems) {
+                            url = buildUrl(new String[] {baseUrl, DEPLOYMENTS}, new String[] {
+                                "_include",
+                                include,
+                                "_sort", "-updated_at", "_sort", "-created_at", "_size",
+                                new Integer(pageSize).toString(), "_offset",
+                                new Integer(deplPgOffset).toString()});
+                            response = restTemplate.exchange(url, HttpMethod.GET, entity,
+                                new ParameterizedTypeReference<CloudifyDeploymentList>() {});
+                            deplPgOffset += pageSize;
+                            deployments.addAll(response.getBody().items);
+                        }
+                } else {
+                    deployments.addAll(itemList);
+                }
+        }          
+        // apply user role based auth 
+        Set<String> userRoleSet = (Set<String>) request.getAttribute("userRoles");
+        Set<String> userApps = (Set<String>) request.getAttribute("userApps");
+
+        Predicate<String> adminPred =
+            p -> p.contains("System_Administrator") || p.contains("Write_Access");
+
+        Predicate<String> ecompSuperPred =
+            p -> p.contains("ECOMPC_WRITE") || p.contains("ECOMPC_READ");
+         
+        if (userRoleSet.stream().noneMatch(adminPred)) {
+            if (userRoleSet.stream().noneMatch(ecompSuperPred)) {
+                deployments = (List<CloudifyDeployment>) deployments.stream().filter(s -> userApps
+                    .stream()
+                    .anyMatch(appFilter -> (((CloudifyDeployment) s).id.toLowerCase().indexOf(appFilter) == 0)))
+                    .collect(Collectors.<CloudifyDeployment>toList());
+            } else {
+                Predicate<CloudifyDeployment> appFilter = p -> p.id.toLowerCase().indexOf("dcae") == -1;
+                deployments = (List<CloudifyDeployment>) deployments.stream().filter(appFilter)
+                    .collect(Collectors.toList());
+            }
+        }
+
+        List<CloudifyDeployment> filteredDeployments = deployments;
+        //-------------------ServiceId Filter-------------------//
+       if (filterJson.has("serviceId")) {
+               String serviceIdFilterString;
+               Object serviceIdObject = filterJson.get("serviceId");
+
+               //Check for logic operators
+               if (serviceIdObject instanceof JSONObject) { 
+                       JSONObject serviceIdJsonObject = filterJson.getJSONObject("serviceId");
+                       if (serviceIdJsonObject.has("$not")) {
+                               serviceIdFilterString = serviceIdJsonObject.getString("$not");
+                               filteredDeployments = serviceIdFilter(serviceIdFilterString, filteredDeployments, true);
+                       }
+                       else {
+                               throw new Exception("ERROR: Not a valid logic operator");
+                       }
+               }
+               else if (serviceIdObject instanceof String) {
+                       serviceIdFilterString = filterJson.getString("serviceId");
+                       filteredDeployments = serviceIdFilter(serviceIdFilterString, filteredDeployments, false);
+               }
+       }
+        
+        //------------------Handle Input Filter--------------//
+       if (filterJson.has("input")) {
+               JSONObject inputFilterObject;
+               Object inputObject = filterJson.get("input");
+
+               //Check for logic operators
+               if (inputObject instanceof JSONObject) { 
+                       JSONObject inputJsonObject = filterJson.getJSONObject("input");
+                       if (inputJsonObject.has("$not")) {
+                               inputFilterObject = inputJsonObject.getJSONObject("$not");
+                               filteredDeployments = inputFilter(inputFilterObject, filteredDeployments, true);
+                       }
+                       //If no operators, pass to filter func
+                       else {
+                               inputFilterObject = inputJsonObject;
+                               filteredDeployments = inputFilter(inputFilterObject, filteredDeployments, false);
+                       }
+               }
+       }
+
+       //-------------------Install Status Filter-------------------//
+       if (filterJson.has("installStatus")) {
+               String installStatusFilterString;
+               Object installStatusObject = filterJson.get("installStatus");
+
+               //Check for logic operators
+               if (installStatusObject instanceof JSONObject) { 
+                       JSONObject installStatusJsonObject = filterJson.getJSONObject("installStatus");
+                       if (installStatusJsonObject.has("$not")) {
+                               installStatusFilterString = installStatusJsonObject.getString("$not");
+                               filteredDeployments = installStatusFilter(installStatusFilterString, filteredDeployments, true);
+                       }
+                       else {
+                               throw new Exception("ERROR: Not a valid logic operator");
+                       }
+               }
+               else if (installStatusObject instanceof String) {
+                       installStatusFilterString = filterJson.getString("installStatus");
+                       filteredDeployments = installStatusFilter(installStatusFilterString, filteredDeployments, false);
+               }
+       }
+        
+      //-------------------isHelm Filter-------------------//
+       if (filterJson.has("isHelm")) {
+               String helmFilterString;
+               Object helmObject = filterJson.get("isHelm");
+
+               //Check for logic operators
+               if (helmObject instanceof JSONObject) { 
+                       JSONObject helmJsonObject = filterJson.getJSONObject("isHelm");
+                       if (helmJsonObject.has("$not")) {
+                               helmFilterString = helmJsonObject.getString("$not");
+                               filteredDeployments = helmFilter(helmFilterString, filteredDeployments, true);
+                       }
+                       else {
+                               throw new Exception("ERROR: Not a valid logic operator");
+                       }
+               }
+               else if (helmObject instanceof String) {
+                       helmFilterString = filterJson.getString("isHelm");
+                       filteredDeployments = helmFilter(helmFilterString, filteredDeployments, false);
+               }
+       }              
+        //CloudifyDeploymentList filteredDepList = new CloudifyDeploymentList(filteredDeployments, null);
+        return filteredDeployments;
+    }
+    
+    /*
+     * Helper function to handle the tenant filter
+     */
+    private List<CloudifyTenant> tenantFilter(String filterString, boolean isNot) throws Exception {
+       CloudifyTenantList availableTenants = getTenants();
+       List<CloudifyTenant> selectedTenants = new ArrayList<CloudifyTenant>();
+       
+               //If using tenant filter, verify its valid tenant name
+       if (filterString != null && !filterString.isEmpty()) {
+               for (CloudifyTenant tenant : availableTenants.items) {
+               if (!isNot && tenant.name.equals(filterString)) {
+                       selectedTenants.add(tenant);
+               }
+               else if (isNot && !tenant.name.equals(filterString)) {
+                       selectedTenants.add(tenant);
+               }
+            }
+               if (selectedTenants.isEmpty()) {
+                       throw new Exception("ERROR: Tenant filter was used but resulted in no selected tenants");
+               }
+       }
+               //If no proper tenants given
+       else {
+               throw new Exception("ERROR: Tenant filter was used but no tenants were given");
+       }
+       return selectedTenants;
+    }
+      
+    
+    /*
+     * Helper function to filter deployments by serviceId
+     */
+    private List<CloudifyDeployment> serviceIdFilter(String filterString, List<CloudifyDeployment> deployments, boolean isNot) throws Exception {
+       List<CloudifyDeployment> newFilteredDeployments = new ArrayList<CloudifyDeployment>();
+        if (filterString != null && !filterString.isEmpty()) {
+               for (CloudifyDeployment dep : deployments) {
+                       if (!isNot && dep.id.contains(filterString))
+                               newFilteredDeployments.add(dep);
+                       else if (isNot && !dep.id.contains(filterString))
+                               newFilteredDeployments.add(dep);
+               }
+        }
+        else {
+               throw new Exception("ERROR: Service ID filter was used but a valid serviceId String was not provided");
+        }
+        return newFilteredDeployments;
+    }
+    
+    
+    /*
+     * Helper function to filter deployments by input
+     */
+    private List<CloudifyDeployment> inputFilter(JSONObject filterJson, List<CloudifyDeployment> deployments, boolean isNot) throws Exception {
+       List<CloudifyDeployment> newFilteredDeployments = new ArrayList<CloudifyDeployment>();
+        if (filterJson != null && filterJson.has("inputKey") && filterJson.has("inputValue") &&
+                       !filterJson.isNull("inputKey") && !filterJson.isNull("inputValue")) {
+               String inputKey = filterJson.getString("inputKey");
+               String inputValue = filterJson.getString("inputValue");
+               
+               ///For now, only allow the use of aaf_username and dcaeTargetType input key
+               if (!inputKey.equals("aaf_username") && !inputKey.equals("dcae_target_type"))
+                       throw new Exception("ERROR: This input key is NOT supported");
+               
+               //For each deployment, get the input keys that contain <inputKey>
+            //then check their value to see if it contains the desired <inputValue>
+               for (CloudifyDeployment dep : deployments) {
+                       if (dep.inputs == null)
+                               throw new Exception("ERROR: Deployment inputs not found, 'inputs' must be in the include filter for input filtering");
+                       Set<String> filteredDepInputKeys = dep.inputs.keySet().stream()
+                               .filter(s -> s.contains(inputKey)).collect(Collectors.toSet());
+               for (String filteredKey : filteredDepInputKeys) {
+                       String value = dep.inputs.get(filteredKey).toString();
+                       if (!isNot && value.equals(inputValue)) {
+                               newFilteredDeployments.add(dep);
+                               break;
+                       }
+                       else if (isNot && !value.equals(inputValue)) {
+                               newFilteredDeployments.add(dep);
+                               break;
+                       }
+               }
+               }
+        }
+        else { //If filter used but no valid KV found
+               throw new Exception("ERROR: Input filter was used but a valid inputKey and inputValue was not provided");
+        }
+        return newFilteredDeployments;
+    }
+    
+    /*
+     * Helper function to filter deployments by install status
+     */
+    private List<CloudifyDeployment> installStatusFilter(String filterString, List<CloudifyDeployment> deployments, boolean isNot) throws Exception {
+       List<CloudifyDeployment> newFilteredDeployments = new ArrayList<CloudifyDeployment>();
+        if (filterString != null && !filterString.isEmpty()) {
+               
+               //For each deployment, get execution status and compare to filter
+               for (CloudifyDeployment dep : deployments) {
+                       List<CloudifyExecution> executions = getInstallExecutionSummary(dep.id, dep.tenant_name).items;
+                       if (executions.size() > 0) {
+                               String status = executions.get(0).status;
+                               if (!isNot && status.equals(filterString)) {
+                                       newFilteredDeployments.add(dep);
+                               }
+                               else if (isNot && !status.equals(filterString)) {
+                                       newFilteredDeployments.add(dep);
+                               }
+                       }
+               }
+        }
+        else { //If using filter but invalid install status given
+               throw new Exception("ERROR: Install Status filter was used but a valid installStatus String was not provided");
+        }
+        return newFilteredDeployments;
+    }
+    
+    /*
+     * Helper function to filter by isHelm
+     */
+    private List<CloudifyDeployment> helmFilter(String filterJson, List<CloudifyDeployment> deployments, boolean isNot) {
+       List<CloudifyDeployment> newFilteredDeployments = new ArrayList<CloudifyDeployment>();
+        if (filterJson != null && !filterJson.isEmpty()) {
+               
+               //For each deployment, get blueprint and see if it has helm plugin and compare to filter
+               for (CloudifyDeployment dep : deployments) {
+                CloudifyBlueprintList bpList = getBlueprint(dep.blueprint_id, dep.tenant_name);
+                Map<String, Object> bpPlan = bpList.items.get(0).plan;               
+                Map<String, String> workflows = (Map<String, String>) bpPlan.get("workflows");
+                Map<String, String> pluginInfo = ((List<Map<String, String>>) bpPlan
+                                                                               .get("deployment_plugins_to_install")).get(0);
+                if (pluginInfo.get("name").equals("helm-plugin")) {
+                       if (!isNot && (filterJson.equals("true") || filterJson.equals("True") || filterJson.equals("TRUE")))
+                               newFilteredDeployments.add(dep);
+                       else if (isNot && (filterJson.equals("false") || filterJson.equals("False") || filterJson.equals("FALSE")))
+                               newFilteredDeployments.add(dep);
+                }
+                else
+                       if (!isNot && (filterJson.equals("false") || filterJson.equals("False") || filterJson.equals("FALSE")))
+                               newFilteredDeployments.add(dep);
+                       else if (isNot && (filterJson.equals("true") || filterJson.equals("True") || filterJson.equals("TRUE")))
+                               newFilteredDeployments.add(dep);
+               }
+        }
+        else { //If not using filter, just return original deployments
+               newFilteredDeployments = deployments;
+        }
+        return newFilteredDeployments;
+    }
 
     @Override
     public CloudifyDeploymentList getDeployment(final String id) {
-        String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, new String[] { "id", id });
+        String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, new String[] { "id", id, "_all_tenants", "true" });
         logger.debug(EELFLoggerDelegate.debugLogger, "getDeployment: url {}", url);
         ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, null,
                 new ParameterizedTypeReference<CloudifyDeploymentList>() {
@@ -267,7 +1042,7 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl
 
     @Override
     public CloudifyDeploymentList getDeployment(final String id, final String tenant) {
-        String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, new String[] { "id", id, TENANT, tenant });
+        String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, new String[] { "id", id});
         logger.debug(EELFLoggerDelegate.debugLogger, "getDeployment: url {}", url);
         HttpEntity<String> entity = getTenantHeader(tenant);
         ResponseEntity<CloudifyDeploymentList> response = restTemplate.exchange(url, HttpMethod.GET, entity,
@@ -285,4 +1060,44 @@ public class CloudifyRestClientImpl extends RestClientBase implements CloudifyCl
             entity, new ParameterizedTypeReference<CloudifyDeploymentList>() {});
         return response.getBody();
     }
+    
+    /**
+     * Get a cloudify secret
+     * 
+     * @return CloudifySecret
+     */
+    @Override
+    public CloudifySecret getSecret(String secretName, String tenant) {
+        String url = buildUrl(new String[] { baseUrl, SECRETS, secretName }, null);
+        logger.debug(EELFLoggerDelegate.debugLogger, "getSecrets: url {}", url);
+        HttpEntity<String> entity = getTenantHeader(tenant);
+        ResponseEntity<CloudifySecret> response = restTemplate.exchange(url, HttpMethod.GET, entity,
+                new ParameterizedTypeReference<CloudifySecret>() {
+                });
+        return response.getBody();
+    }
+
+    /**
+     * Get the list of cloudify plugins
+     * 
+     * @return List<CloudifyPlugin>
+     */
+    public CloudifyPluginList getPlugins() {
+        String url = buildUrl(new String[] { baseUrl, PLUGINS }, null);
+        logger.debug(EELFLoggerDelegate.debugLogger, "getPlugins: url {}", url);
+        ResponseEntity<CloudifyPluginList> response = restTemplate.exchange(url, HttpMethod.GET, null,
+                new ParameterizedTypeReference<CloudifyPluginList>() {
+                });
+        CloudifyPluginList result = response.getBody();
+        return result;
+    }
+    
+    @Override
+    public void deleteBlueprint(String bpName, String tenant) {
+        String url = buildUrl(new String[] { baseUrl, BLUEPRINTS, bpName }, null);
+        logger.debug(EELFLoggerDelegate.debugLogger, "deleteBlueprint: url {}", url);
+        HttpEntity<String> entity = getTenantHeader(tenant);
+        restTemplate.exchange(url, HttpMethod.DELETE, entity, new ParameterizedTypeReference<CloudifyBlueprint>() {
+        });
+    }
 }
index c63652b..90da400 100644 (file)
  *******************************************************************************/
 package org.onap.ccsdk.dashboard.rest;
 
+import java.net.URL;
 import java.util.List;
 
-import org.onap.ccsdk.dashboard.model.ConsulDatacenter;
-import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration;
-import org.onap.ccsdk.dashboard.model.ConsulNodeInfo;
-import org.onap.ccsdk.dashboard.model.ConsulServiceHealth;
-import org.onap.ccsdk.dashboard.model.ConsulServiceInfo;
+import org.onap.ccsdk.dashboard.model.consul.ConsulDatacenter;
+import org.onap.ccsdk.dashboard.model.consul.ConsulDeploymentHealth;
+import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration;
+import org.onap.ccsdk.dashboard.model.consul.ConsulNodeInfo;
+import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth;
+import org.onap.ccsdk.dashboard.model.consul.ConsulServiceInfo;
+import org.springframework.web.client.RestTemplate;
 
 /**
  * Defines the interface of the Consul REST client.
@@ -48,6 +51,16 @@ public interface ConsulClient {
      * @return List of ConsulServiceHealth
      */
     public List<ConsulServiceHealth> getServiceHealth(String datacenter, String srvcName);
+    
+    /**
+     * Gets the status for the service which corresponds to deployment Id on all nodes.
+     * Filters services on Consul to find services that contain service tag that 
+     * matches the given deployment id
+     * 
+     * @param deploymentId Deployment Id
+     * @return List of ConsulServiceHealth
+     */
+    public ConsulDeploymentHealth getServiceHealthByDeploymentId(String deploymentId);
 
     /**
      * Gets all the nodes that are monitored by Consul.
@@ -71,20 +84,4 @@ public interface ConsulClient {
      */
     public List<ConsulDatacenter> getDatacenters();
 
-    /**
-     * Registers a service with Consul for health check.
-     * 
-     * @param registration Details about the service to be registered.
-     * @return Result of registering a service
-     */
-    public String registerService(ConsulHealthServiceRegistration registration);
-
-    /**
-     * Deregisters a service with Consul for health check.
-     * 
-     * @param serviceName Name of the service to be deregistered.
-     * @return Response code
-     */
-    public int deregisterService(String serviceName);
-
 }
index 2567577..911e342 100644 (file)
@@ -29,15 +29,25 @@ import java.util.Map;
 
 import javax.annotation.PostConstruct;
 
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
 import org.json.JSONArray;
 import org.json.JSONObject;
-import org.onap.ccsdk.dashboard.model.ConsulDatacenter;
-import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration;
-import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration.EndpointCheck;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList;
+import org.onap.ccsdk.dashboard.model.consul.ConsulDatacenter;
+import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration;
+import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration.EndpointCheck;
+import org.onap.ccsdk.dashboard.model.consul.ConsulNodeInfo;
+import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth;
+import org.onap.ccsdk.dashboard.model.consul.ConsulServiceInfo;
+import org.onap.ccsdk.dashboard.model.consul.ConsulDeploymentHealth;
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
-import org.onap.ccsdk.dashboard.model.ConsulNodeInfo;
-import org.onap.ccsdk.dashboard.model.ConsulServiceHealth;
-import org.onap.ccsdk.dashboard.model.ConsulServiceInfo;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.HttpEntity;
@@ -45,6 +55,9 @@ import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.HttpStatusCodeException;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestTemplate;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -55,18 +68,27 @@ public class ConsulRestClientImpl extends RestClientBase implements ConsulClient
     private static EELFLoggerDelegate logger =
         EELFLoggerDelegate.getLogger(ConsulRestClientImpl.class);
     private String baseUrl;
-    private final ObjectMapper objectMapper = new ObjectMapper();
+    private String consul_acl_token;
+    private HttpEntity<String> token_entity;
 
     private static final String API_VER = "v1";
     private static final String CATALOG = "catalog";
     private static final String SERVICES = "services";
     private static final String HEALTH = "health";
     private static final String CHECKS = "checks";
+    private static final String STATE = "state";
+    private static final String ANY = "any";
 
     @PostConstruct
     public void init() {
-        String webapiUrl = DashboardProperties.getControllerProperty("dev",
-            DashboardProperties.CONTROLLER_SUBKEY_CONSUL_URL);
+        if (consul_acl_token == null || consul_acl_token.isEmpty()) {
+            consul_acl_token = getConsulAcl();  
+        }
+        if (consul_acl_token != null && !consul_acl_token.isEmpty()) {
+            token_entity = getConsulTokenHeader(consul_acl_token);
+        }
+        String webapiUrl = DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_CONSUL_URL);
         if (webapiUrl == null)
             throw new IllegalArgumentException("Null URL not permitted");
         URL url = null;
@@ -82,136 +104,271 @@ public class ConsulRestClientImpl extends RestClientBase implements ConsulClient
         }
     }
 
+    protected String getConsulAcl() {
+        return getConsulAcl(null);
+    }
+    
+    protected String getConsulAcl(RestTemplate cfyRest) {
+        String acl_token = null;
+        String webapiUrl = DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_CLOUDIFY_URL);
+        String cfyBaseUrl = "";
+        if (webapiUrl != null) {            
+            String user = DashboardProperties.getControllerProperty("site.primary",
+                DashboardProperties.SITE_SUBKEY_CLOUDIFY_USERNAME);
+            String pass = DashboardProperties.getControllerProperty("site.primary",
+                DashboardProperties.SITE_SUBKEY_CLOUDIFY_PASS);
+            URL url = null;
+            try {
+                url = new URL(webapiUrl);
+                cfyBaseUrl = url.toExternalForm();
+                String urlScheme = webapiUrl.split(":")[0];
+                if (cfyRest == null) {
+                    cfyRest = 
+                        createCfyRestTemplate(url, user, pass, urlScheme);
+                }
+                String urlStr = buildUrl(new String[] { cfyBaseUrl, "secrets", "eom-dashboard-acl-token" }, null);
+                logger.debug(EELFLoggerDelegate.debugLogger, "getAclSecret: url {}", urlStr);
+
+                ResponseEntity<CloudifySecret> response = cfyRest.exchange(urlStr, HttpMethod.GET, null,
+                    new ParameterizedTypeReference<CloudifySecret>() {
+                    });
+                acl_token = response.getBody().getValue();                
+            } catch (MalformedURLException me) {
+                //throw new RuntimeException("Failed to parse URL", ex);
+                logger.error(EELFLoggerDelegate.errorLogger, "Failed to parse URL - malformed" + me.getMessage());
+            } catch (Exception e) {
+                logger.error(EELFLoggerDelegate.errorLogger, e.getMessage());
+                acl_token = "";
+            }
+        }
+        return acl_token;
+    }
+    
+    protected RestTemplate createCfyRestTemplate(URL url, String user, String pass, String urlScheme)  throws Exception {       
+        RestTemplate restTempl = null;
+        final HttpHost httpHost = new HttpHost(url.getHost(), url.getPort(), urlScheme);
+        // Build a client with a credentials provider
+        CloseableHttpClient httpClient = null;
+
+        if (user != null && pass != null) {
+            CredentialsProvider credsProvider = new BasicCredentialsProvider();
+            credsProvider.setCredentials(new AuthScope(httpHost), new UsernamePasswordCredentials(user, pass));
+            httpClient = HttpClientBuilder.create().setDefaultCredentialsProvider(credsProvider).build();
+        } else {
+            httpClient = HttpClientBuilder.create().build();
+        }
+        // Create request factory
+        HttpComponentsClientHttpRequestFactoryBasicAuth requestFactory = new HttpComponentsClientHttpRequestFactoryBasicAuth(
+                httpHost);
+        requestFactory.setHttpClient(httpClient);
+        restTempl = new RestTemplate();
+        restTempl.setRequestFactory(requestFactory);
+        return restTempl;
+    }
+    
+    /**
+     * @param consul_acl_token the consul_acl_token to set
+     */
+    public void setConsul_acl_token(String consul_acl_token) {
+        this.consul_acl_token = consul_acl_token;
+    }
+    
     @Override
     public List<ConsulServiceHealth> getServiceHealth(String dc, String srvc) {
         String url = buildUrl(new String[] { baseUrl, API_VER, HEALTH, CHECKS, srvc }, new String[] { "dc", dc });
         logger.debug(EELFLoggerDelegate.debugLogger, "getServiceHealth: url {}", url);
-        ResponseEntity<List<ConsulServiceHealth>> response = restTemplate.exchange(url, HttpMethod.GET, null,
+        ResponseEntity<List<ConsulServiceHealth>> response = null;
+        try {
+            response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
+                    new ParameterizedTypeReference<List<ConsulServiceHealth>>() {
+                    });         
+        } catch (HttpStatusCodeException e) {
+            if (e.getStatusCode().value() == 403) {
+                // update consul ACL token header and retry
+                consul_acl_token = getConsulAcl();
+                if (consul_acl_token != null && !consul_acl_token.isEmpty()) {
+                    token_entity = getConsulTokenHeader(consul_acl_token);
+                    response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
+                        new ParameterizedTypeReference<List<ConsulServiceHealth>>() {
+                        }); 
+                } else {
+                    throw e;
+                }             
+            }
+        }
+        if (!response.getBody().isEmpty()) {
+            return response.getBody();
+        } else {
+            return null;
+        }
+    }
+    
+    @Override
+    public ConsulDeploymentHealth getServiceHealthByDeploymentId(String deploymentId) {
+        String url = buildUrl(new String[] { baseUrl, API_VER, HEALTH, STATE, ANY }, 
+                       new String[] {"filter", "ServiceTags contains " + "\"" + deploymentId + "\""});
+        logger.debug(EELFLoggerDelegate.debugLogger, "getServiceHealthByDeploymentId: url {}", url);
+        ResponseEntity<List<ConsulServiceHealth>> response = null;
+        try {
+            response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
                 new ParameterizedTypeReference<List<ConsulServiceHealth>>() {
                 });
-        return response.getBody();
+        } catch (HttpStatusCodeException e) {
+            if (e.getStatusCode().value() == 403) {
+                // update consul ACL token header and retry
+                consul_acl_token = getConsulAcl();
+                if (consul_acl_token != null && !consul_acl_token.isEmpty()) {
+                    token_entity = getConsulTokenHeader(consul_acl_token);
+                    response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
+                        new ParameterizedTypeReference<List<ConsulServiceHealth>>() {
+                        });                   
+                } else {
+                    throw e;
+                }             
+            }
+        }
+        if (!response.getBody().isEmpty()) {
+            return new ConsulDeploymentHealth.Builder(response.getBody().get(0)).build();
+        } else {
+            return null;
+        }
     }
 
     @Override
     public List<ConsulServiceInfo> getServices(String dc) {
         String url = buildUrl(new String[] { baseUrl, API_VER, CATALOG, SERVICES }, new String[] { "dc", dc });
         logger.debug(EELFLoggerDelegate.debugLogger, "getServices: url {}", url);
-        ResponseEntity<Map<String, Object>> response = restTemplate.exchange(url, HttpMethod.GET, null,
+        ResponseEntity<Map<String, Object>> response = null;
+        try {
+            response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
                 new ParameterizedTypeReference<Map<String, Object>>() {
                 });
-        Map<String, Object> serviceInfo = response.getBody();
-        List<ConsulServiceInfo> list = new ArrayList<>();
-        for (Map.Entry<String, Object> entry : serviceInfo.entrySet()) {
-            // Be defensive
-            List<String> addrs = null;
-            if (entry.getValue() instanceof List<?>)
-                addrs = (List<String>) entry.getValue();
-            else
-                addrs = new ArrayList<>();
-            list.add(new ConsulServiceInfo(entry.getKey(), addrs));
-        }
-        return list;
+        } catch (HttpStatusCodeException e) {
+            if (e.getStatusCode().value() == 403) {
+                // update consul ACL token header and retry
+                consul_acl_token = getConsulAcl();
+                if (consul_acl_token != null && !consul_acl_token.isEmpty()) {
+                    token_entity = getConsulTokenHeader(consul_acl_token);
+                    response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
+                        new ParameterizedTypeReference<Map<String, Object>>() {
+                        });                  
+                } else {
+                    throw e;
+                }             
+            }
+        }
+        if (!response.getBody().isEmpty()) {
+            Map<String, Object> serviceInfo = response.getBody();
+            List<ConsulServiceInfo> list = new ArrayList<>();
+            for (Map.Entry<String, Object> entry : serviceInfo.entrySet()) {
+                // Be defensive
+                List<String> addrs = null;
+                if (entry.getValue() instanceof List<?>)
+                    addrs = (List<String>) entry.getValue();
+                else
+                    addrs = new ArrayList<>();
+                list.add(new ConsulServiceInfo(entry.getKey(), addrs));
+            }
+            return list;
+        } else {
+            return null;
+        }
     }
 
     @Override
     public List<ConsulNodeInfo> getNodes(String dc) {
         String url = buildUrl(new String[] { baseUrl, API_VER, CATALOG, "nodes" }, new String[] { "dc", dc });
         logger.debug(EELFLoggerDelegate.debugLogger, "getNodesHealth: url {}", url);
-        ResponseEntity<List<ConsulNodeInfo>> response = restTemplate.exchange(url, HttpMethod.GET, null,
+        ResponseEntity<List<ConsulNodeInfo>> response = null;
+        try {
+            response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
                 new ParameterizedTypeReference<List<ConsulNodeInfo>>() {
                 });
-        return response.getBody();
+        } catch (HttpStatusCodeException e) {
+            if (e.getStatusCode().value() == 403) {
+                // update consul ACL token header and retry
+                consul_acl_token = getConsulAcl();
+                if (consul_acl_token != null && !consul_acl_token.isEmpty()) {
+                    token_entity = getConsulTokenHeader(consul_acl_token);
+                    response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
+                        new ParameterizedTypeReference<List<ConsulNodeInfo>>() {
+                        });                 
+                } else {
+                    throw e;
+                }             
+            }
+        }
+        if (!response.getBody().isEmpty()) {
+            return response.getBody();
+        } else {
+            return null;
+        }
     }
 
     @Override
     public List<ConsulServiceHealth> getNodeServicesHealth(String dc, String nodeId) {
         String url = buildUrl(new String[] { baseUrl, API_VER, HEALTH, "node", nodeId }, new String[] { "dc", dc });
         logger.debug(EELFLoggerDelegate.debugLogger, "getNodeServicesHealth: url {}", url);
-        ResponseEntity<List<ConsulServiceHealth>> response = restTemplate.exchange(url, HttpMethod.GET, null,
+        ResponseEntity<List<ConsulServiceHealth>> response = null;
+        try {
+            response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
                 new ParameterizedTypeReference<List<ConsulServiceHealth>>() {
                 });
-        return response.getBody();
+        } catch (HttpStatusCodeException e) {
+            if (e.getStatusCode().value() == 403) {
+                // update consul ACL token header and retry
+                consul_acl_token = getConsulAcl();
+                if (consul_acl_token != null && !consul_acl_token.isEmpty()) {
+                    token_entity = getConsulTokenHeader(consul_acl_token);
+                    response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
+                        new ParameterizedTypeReference<List<ConsulServiceHealth>>() {
+                    });             
+                } else {
+                    throw e;
+                }             
+            }
+        }
+        if (!response.getBody().isEmpty()) {
+            return response.getBody();
+        } else {
+            return null;
+        }
     }
 
     @Override
     public List<ConsulDatacenter> getDatacenters() {
         String url = buildUrl(new String[] { baseUrl, API_VER, CATALOG, "datacenters" }, null);
         logger.debug(EELFLoggerDelegate.debugLogger, "getDatacentersHealth: url {}", url);
-        ResponseEntity<List<String>> response = restTemplate.exchange(url, HttpMethod.GET, null,
+        ResponseEntity<List<String>> response = null;
+        try {
+            response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
                 new ParameterizedTypeReference<List<String>>() {
                 });
-        List<String> list = response.getBody();
-        List<ConsulDatacenter> result = new ArrayList<>();
-        for (String dc : list)
-            result.add(new ConsulDatacenter(dc));
-        return result;
-    }
-
-    @Override
-    public String registerService(ConsulHealthServiceRegistration registration) {
-        String url = buildUrl(new String[] { baseUrl, API_VER, "/agent/service/register" }, null);
-        logger.debug(EELFLoggerDelegate.debugLogger, "registerService: url {}", url);
-        String resultStr = "";
-        JSONObject outputJson = new JSONObject();
-        JSONObject checkObject = new JSONObject();
-        List<EndpointCheck> checks = registration.services.get(0).checks;
-        String service_name = registration.services.get(0).name;
-        String service_port = registration.services.get(0).port;
-        String service_address = registration.services.get(0).address;
-        List<String> tags = registration.services.get(0).tags;
-
-        outputJson.put("Name", service_name);
-        outputJson.put("ID", service_name);
-        outputJson.put("Port", Integer.parseInt(service_port));
-        outputJson.put("Address", service_address);
-        outputJson.put("Tags", tags);
-
-        if (checks.size() == 1) {
-            checkObject.put("HTTP", checks.get(0).endpoint);
-            checkObject.put("Interval", checks.get(0).interval);
-            if (!checks.get(0).description.isEmpty())
-                checkObject.put("Notes", checks.get(0).description);
-            checkObject.put("ServiceID", service_name);
-            outputJson.put("Check", checkObject);
-        } else {
-            JSONArray checks_new = new JSONArray();
-            for (EndpointCheck check : checks) {
-                checkObject.put("HTTP", check.endpoint);
-                checkObject.put("Interval", check.endpoint);
-                if (!check.description.isEmpty())
-                    checkObject.put("Notes", check.description);
-                checkObject.put("ServiceID", service_name);
-                checks_new.put(checkObject);
+        } catch (HttpStatusCodeException e) {
+            if (e.getStatusCode().value() == 403) {
+                // update consul ACL token header and retry
+                consul_acl_token = getConsulAcl();
+                if (consul_acl_token != null && !consul_acl_token.isEmpty()) {
+                    token_entity = getConsulTokenHeader(consul_acl_token);
+                    response = restTemplate.exchange(url, HttpMethod.GET, token_entity,
+                        new ParameterizedTypeReference<List<String>>() {
+                        });             
+                } else {
+                    throw e;
+                }             
             }
-            outputJson.put("Checks", checks_new);
         }
-        HttpHeaders headers = new HttpHeaders();
-        headers.setContentType(MediaType.APPLICATION_JSON);
-        HttpEntity<String> entity = new HttpEntity<String>(outputJson.toString(), headers);
-        ResponseEntity<JSONObject> result = restTemplate.exchange(url, HttpMethod.PUT, entity,
-                new ParameterizedTypeReference<JSONObject>() {
-                });
-        try {
-            resultStr = objectMapper.writeValueAsString(result);
-        } catch (JsonProcessingException e) {
-
-        } finally {
-        }
-        return resultStr;
+        if (!response.getBody().isEmpty()) {
+            List<String> list = response.getBody();
+            List<ConsulDatacenter> result = new ArrayList<>();
+            for (String dc : list)
+                result.add(new ConsulDatacenter(dc));
+            return result;
+        } else {
+            return null;
+        }       
 
     }
 
-    @Override
-    public int deregisterService(String serviceName) {
-        String url = buildUrl(new String[] { baseUrl, API_VER, "/agent/service/deregister", serviceName }, null);
-        logger.debug(EELFLoggerDelegate.debugLogger, "deregisterService: url {}", url);
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.setContentType(MediaType.APPLICATION_JSON);
-        HttpEntity<String> entity = new HttpEntity<String>(headers);
-        ResponseEntity<JSONObject> result = restTemplate.exchange(url, HttpMethod.PUT, entity,
-                new ParameterizedTypeReference<JSONObject>() {
-                });
-        return result.getStatusCode().value();
-    }
 }
index 0804e9a..012ec32 100644 (file)
@@ -23,6 +23,8 @@ package org.onap.ccsdk.dashboard.rest;
 
 import java.util.stream.Stream;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.onap.ccsdk.dashboard.exceptions.BadRequestException;
 import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException;
 import org.onap.ccsdk.dashboard.exceptions.DownstreamException;
@@ -34,6 +36,11 @@ import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse;
 
 public interface DeploymentHandlerClient {
 
+    /**
+     * Run deployment handler service health check
+     * 
+     */
+    public String checkHealth();
     /**
      * Gets a list of all service deployments known to the orchestrator.
      * 
@@ -65,17 +72,16 @@ public interface DeploymentHandlerClient {
      *         /dcae-deployments/{deploymentId}
      *
      */
-    public DeploymentResponse putDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest)
+    public DeploymentResponse putDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest,
+        HttpServletRequest request)
             throws BadRequestException, ServiceAlreadyExistsException, ServerErrorException, DownstreamException;
 
     /**
-     * Initiate update for a deployment
+     * For API use, Request deployment of a DCAE Service.
      * 
      * @param deploymentId      Unique deployment identifier assigned by the API
      *                          client.
      * 
-     * @param tenant            Cloudify tenant where the deployment should be done
-     * 
      * @param deploymentRequest Deployment request object that contains the
      *                          necessary fields for service deployment.
      * 
@@ -83,7 +89,7 @@ public interface DeploymentHandlerClient {
      *         /dcae-deployments/{deploymentId}
      *
      */
-    public DeploymentResponse updateDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest)
+    public DeploymentResponse putDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest)
             throws BadRequestException, ServiceAlreadyExistsException, ServerErrorException, DownstreamException;
 
     /**
@@ -93,6 +99,16 @@ public interface DeploymentHandlerClient {
      * @param deploymentId Unique deployment identifier assigned by the API client.
      * 
      */
+    public void deleteDeployment(String deploymentId, String tenant, HttpServletRequest request)
+            throws BadRequestException, ServerErrorException, DownstreamException, DeploymentNotFoundException;
+    
+    /**
+     * For API use, Uninstall the DCAE service and remove all associated data from the
+     * orchestrator.
+     * 
+     * @param deploymentId Unique deployment identifier assigned by the API client.
+     * 
+     */
     public void deleteDeployment(String deploymentId, String tenant)
             throws BadRequestException, ServerErrorException, DownstreamException, DeploymentNotFoundException;
 }
index 6e9ecb4..803c710 100644 (file)
@@ -24,21 +24,35 @@ package org.onap.ccsdk.dashboard.rest;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.stream.Stream;
 
 import javax.annotation.PostConstruct;
+import javax.servlet.http.HttpServletRequest;
 
 import org.onap.ccsdk.dashboard.exceptions.BadRequestException;
 import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException;
 import org.onap.ccsdk.dashboard.exceptions.DownstreamException;
 import org.onap.ccsdk.dashboard.exceptions.ServerErrorException;
 import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentExt;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentHelm;
 import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentErrorResponse;
 import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentLink;
 import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest;
 import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse;
 import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentsListResponse;
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
+import org.onap.portalsdk.core.objectcache.AbstractCacheManager;
+import org.onap.portalsdk.core.web.support.UserUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.ParameterizedTypeReference;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
@@ -48,9 +62,7 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.web.client.HttpClientErrorException;
 import org.springframework.web.client.HttpServerErrorException;
 
-import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
 
 @org.springframework.stereotype.Service
 public class DeploymentHandlerClientImpl extends RestClientBase implements DeploymentHandlerClient {
@@ -59,13 +71,28 @@ public class DeploymentHandlerClientImpl extends RestClientBase implements Deplo
 
     private static final String DEPLOYMENTS = "dcae-deployments";
     private static final String UPDATE_PATH = "dcae-deployment-update";
+    private static final String HEALTH_CHECK = "healthcheck";
+    private static final String SERVICE_ID = "service-list";
 
+    @Autowired
+    CloudifyClient cloudifyClient;
+    
+    private AbstractCacheManager cacheManager;   
+    
+    @Autowired
+    public void setCacheManager(AbstractCacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+    }
+
+    public AbstractCacheManager getCacheManager() {
+        return cacheManager;
+    }
     protected final ObjectMapper objectMapper = new ObjectMapper();
 
     @PostConstruct
     public void init() {
-        String webapiUrl = DashboardProperties.getControllerProperty("dev",
-            DashboardProperties.CONTROLLER_SUBKEY_DHANDLER_URL);
+        String webapiUrl = DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_DHANDLER_URL);
         if (webapiUrl == null)
             throw new IllegalArgumentException("Null URL not permitted");
         URL url = null;
@@ -82,6 +109,14 @@ public class DeploymentHandlerClientImpl extends RestClientBase implements Deplo
 
     }
 
+    public String checkHealth() {
+        String url = buildUrl(new String[] { baseUrl, HEALTH_CHECK }, null);
+        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null,
+                new ParameterizedTypeReference<String>() {
+                });
+        return response.getBody();
+    }
+    
     public Stream<DeploymentLink> getDeployments() {
         String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS }, null);
         ResponseEntity<DeploymentsListResponse> response = restTemplate.exchange(url, HttpMethod.GET, null,
@@ -104,48 +139,19 @@ public class DeploymentHandlerClientImpl extends RestClientBase implements Deplo
     @Override
     public DeploymentResponse putDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest)
             throws BadRequestException, ServiceAlreadyExistsException, ServerErrorException, DownstreamException {
-        String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS, deploymentId },
-                new String[] { "cfy_tenant_name", tenant });
-        try {
-            HttpHeaders headers = new HttpHeaders();
-            headers.setContentType(MediaType.APPLICATION_JSON);
-            ResponseEntity<DeploymentResponse> result = restTemplate.exchange(url, HttpMethod.PUT,
-                    new HttpEntity<DeploymentRequest>(deploymentRequest, headers),
-                    new ParameterizedTypeReference<DeploymentResponse>() {
-                    });
-            return result.getBody();
-        } catch (HttpServerErrorException | HttpClientErrorException e) {
-            DeploymentErrorResponse errBody = null;
-            String errMsg = "";
-            try {
-                errBody = objectMapper.readValue(e.getResponseBodyAsString(), DeploymentErrorResponse.class);
-            } catch (IOException e1) {
-                errBody = null;
-            }
-            if (errBody != null) {
-                errMsg = errBody.getMessage();
-            }
-            StringBuilder errDetails = new StringBuilder();
-            errDetails.append(e.getMessage()).append("  ").append(errMsg);
-            if (e.getStatusCode().value() == 400 || e.getStatusCode().value() == 415
-                    || e.getStatusCode().value() == 404) {
-                throw new BadRequestException(errDetails.toString());
-            } else if (e.getStatusCode().value() == 409) {
-                throw new ServiceAlreadyExistsException(errDetails.toString());
-            } else if (e.getStatusCode().value() == 500) {
-                throw new ServerErrorException(errDetails.toString());
-            } else if (e.getStatusCode().value() == 502 || e.getStatusCode().value() == 504) {
-                throw new DownstreamException(errDetails.toString());
-            }
-        }
-        return null;
+        return putDeployment(deploymentId, tenant, deploymentRequest, null);
     }
-
+    
     @Override
-    public DeploymentResponse updateDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest)
+    public DeploymentResponse putDeployment(String deploymentId, String tenant, DeploymentRequest deploymentRequest,
+        HttpServletRequest request)
             throws BadRequestException, ServiceAlreadyExistsException, ServerErrorException, DownstreamException {
-        String url = buildUrl(new String[] { baseUrl, UPDATE_PATH, deploymentId },
+        String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS, deploymentId },
                 new String[] { "cfy_tenant_name", tenant });
+        String user = "";
+        if (request != null) {
+            user = UserUtils.getUserSession(request).getLoginId();
+        }
         try {
             HttpHeaders headers = new HttpHeaders();
             headers.setContentType(MediaType.APPLICATION_JSON);
@@ -153,20 +159,71 @@ public class DeploymentHandlerClientImpl extends RestClientBase implements Deplo
                     new HttpEntity<DeploymentRequest>(deploymentRequest, headers),
                     new ParameterizedTypeReference<DeploymentResponse>() {
                     });
+            //cache handling
+            ReadWriteLock lock = new ReentrantReadWriteLock();
+            lock.readLock().lock();
+            List itemList = 
+                (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + tenant);           
+            List itemExecList = (List<CloudifyDeploymentExt>)getCacheManager().getObject(
+                SERVICE_ID + ":" + tenant + ":ext");  
+            List itemHelmList = (List<CloudifyDeploymentExt>)getCacheManager().getObject(
+                SERVICE_ID + ":" + tenant + ":helm"); 
+            lock.readLock().unlock();
+            if (itemList != null) {
+                // add the new resource into app cache
+                CloudifyDeployment cfyDepl = 
+                    cloudifyClient.getDeploymentResource(deploymentId, tenant);
+                lock.writeLock().lock();
+                itemList.add(0, cfyDepl);
+                lock.writeLock().unlock();
+                if (itemExecList != null) {
+                    List<CloudifyDeployment> thisDep = new ArrayList<CloudifyDeployment>();
+                    thisDep.add(cfyDepl);
+                    List<CloudifyDeploymentExt> thisDepExec = 
+                        cloudifyClient.updateWorkflowStatus(thisDep);
+                    List<CloudifyDeploymentHelm> thisDepHelm = 
+                        cloudifyClient.updateHelmInfo(thisDep);
+                    lock.writeLock().lock();
+                    itemExecList.add(0, thisDepExec.get(0));
+                    itemHelmList.add(0, thisDepHelm.get(0));
+                    lock.writeLock().unlock();
+                }
+                // handle the owner deployment map cache
+                if (!user.isEmpty()) {
+                    CloudifyDeployedTenant updDepl = 
+                        new CloudifyDeployedTenant(cfyDepl.id, cfyDepl.tenant_name, 
+                            cfyDepl.created_at, cfyDepl.updated_at);
+                    lock.readLock().lock();
+                    Map<String, List<CloudifyDeployedTenant>> deplPerOwner = 
+                        (Map<String, List<CloudifyDeployedTenant>>) 
+                        getCacheManager().getObject("owner_deploy_map");
+                    lock.readLock().unlock();
+                    if (deplPerOwner != null) {
+                        List<CloudifyDeployedTenant> currOwnedDepls = deplPerOwner.get(user); 
+                        if (currOwnedDepls != null) {
+                            currOwnedDepls.add(0, updDepl);
+                        } else {
+                            currOwnedDepls = 
+                                new ArrayList<CloudifyDeployedTenant>();
+                            currOwnedDepls.add(updDepl);                    
+                        }
+                        lock.writeLock().lock();
+                        deplPerOwner.put(user, currOwnedDepls);
+                        lock.writeLock().unlock();
+                    } else {
+                        deplPerOwner = new HashMap<String, List<CloudifyDeployedTenant>>();
+                        List<CloudifyDeployedTenant> deplForBpAggr = new ArrayList<CloudifyDeployedTenant>();
+                        deplForBpAggr.add(updDepl);
+                        deplPerOwner.put(user, deplForBpAggr);
+                    }
+                }
+            }
             return result.getBody();
         } catch (HttpServerErrorException | HttpClientErrorException e) {
-            DeploymentErrorResponse errBody = null;
-            String errMsg = "";
-            try {
-                errBody = objectMapper.readValue(e.getResponseBodyAsString(), DeploymentErrorResponse.class);
-            } catch (IOException e1) {
-                errBody = null;
-            }
-            if (errBody != null) {
-                errMsg = errBody.getMessage();
-            }
+            String errBody = null;
+            errBody = e.getResponseBodyAsString();
             StringBuilder errDetails = new StringBuilder();
-            errDetails.append(e.getMessage()).append("  ").append(errMsg);
+            errDetails.append(e.getMessage()).append("  ").append(errBody);
             if (e.getStatusCode().value() == 400 || e.getStatusCode().value() == 415
                     || e.getStatusCode().value() == 404) {
                 throw new BadRequestException(errDetails.toString());
@@ -178,17 +235,62 @@ public class DeploymentHandlerClientImpl extends RestClientBase implements Deplo
                 throw new DownstreamException(errDetails.toString());
             }
         }
-        return null; // Perhaps this should be a proper JSON error response.
+        return null;
     }
 
     @Override
     public void deleteDeployment(String deploymentId, String tenant)
             throws BadRequestException, ServerErrorException, DownstreamException, DeploymentNotFoundException {
+        deleteDeployment(deploymentId, tenant, null);
+    }
+    @Override
+    public void deleteDeployment(String deploymentId, String tenant, HttpServletRequest request)
+            throws BadRequestException, ServerErrorException, DownstreamException, DeploymentNotFoundException {
         String url = buildUrl(new String[] { baseUrl, DEPLOYMENTS, deploymentId },
-                new String[] { "cfy_tenant_name", tenant, "ignore_failure", "true" });
+                new String[] { "cfy_tenant_name", tenant, "force_uninstall", "true" });
         try {
+            String user = "";
+            if (request != null) {
+                user = UserUtils.getUserSession(request).getLoginId();
+            }
             restTemplate.exchange(url, HttpMethod.DELETE, null, new ParameterizedTypeReference<DeploymentResponse>() {
             });
+            CloudifyDeployment cfyDepl = 
+                cloudifyClient.getDeploymentResource(deploymentId, tenant);
+            // remove resource from app cache
+            ReadWriteLock lock = new ReentrantReadWriteLock();
+            lock.readLock().lock();
+            List itemList = 
+                (List<CloudifyDeployment>)getCacheManager().getObject(SERVICE_ID + ":" + tenant);
+            lock.readLock().unlock();
+            if (itemList != null) {
+                lock.writeLock().lock();
+                itemList.remove(cfyDepl);
+                getCacheManager().removeObject(SERVICE_ID + ":" + tenant);
+                // put updated collection back into cache
+                getCacheManager().putObject(SERVICE_ID + ":" + tenant, itemList);
+                lock.writeLock().unlock();
+           }
+            // handle the owner deployment map cache
+            if (!user.isEmpty()) {
+                lock.readLock().lock();
+                Map<String, List<CloudifyDeployedTenant>> deplPerOwner = 
+                    (Map<String, List<CloudifyDeployedTenant>>) 
+                    getCacheManager().getObject("owner_deploy_map");
+                lock.readLock().unlock();
+                if (deplPerOwner != null) {
+                    List<CloudifyDeployedTenant> currOwnedDepls = deplPerOwner.get(user); 
+                    CloudifyDeployedTenant updDepl = 
+                        new CloudifyDeployedTenant(cfyDepl.id, cfyDepl.tenant_name, 
+                            cfyDepl.created_at, cfyDepl.updated_at);
+                    if (currOwnedDepls != null) {
+                        currOwnedDepls.remove(updDepl);
+                        lock.writeLock().lock();
+                        deplPerOwner.put(user, currOwnedDepls);
+                        lock.writeLock().unlock();
+                    }
+                }
+            }
         } catch (HttpServerErrorException | HttpClientErrorException e) {
             DeploymentErrorResponse errBody = null;
             String errMsg = "";
index 1b93bc7..8f19e9b 100644 (file)
@@ -37,19 +37,33 @@ import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceType;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary;
 
 /**
  * Defines the interface of the Inventory Client.
  */
 public interface InventoryClient {
 
+    /**
+     * Run inventory service health check
+     * 
+     */
+    public String checkHealth();
+
+    /**
+     * Get and store in cache, list of all DCAE Service Type objects.
+     * 
+     * @return void
+     */
+    public void cacheServiceTypes();
+    
     /**
      * Gets a list of all DCAE Service Type objects.
      * 
      * @return Collection<ServiceType>
      */
-    public Stream<ServiceType> getServiceTypes();
-
+    public Stream<ServiceTypeSummary> getServiceTypes();
+    
     /**
      * Gets a list of all DCAE Service Type objects that fall under a specified
      * filter.
@@ -59,7 +73,7 @@ public interface InventoryClient {
      * 
      * @return Collection<ServiceType>
      */
-    public Stream<ServiceType> getServiceTypes(ServiceTypeQueryParams serviceTypeQueryParams);
+    public Stream<ServiceTypeSummary> getServiceTypes(ServiceTypeQueryParams serviceTypeQueryParams);
 
     /**
      * Inserts a new DCAE Service Type, or updates an existing instance associated
@@ -117,7 +131,7 @@ public interface InventoryClient {
      * 
      * @return Collection<Service>
      */
-    public Stream<Service> getServices();
+    //public Stream<Service> getServices();
 
     /**
      * Gets a list of all DCAE Service objects that fall under a specified filter.
@@ -127,7 +141,7 @@ public interface InventoryClient {
      * 
      * @return Collection<Service>
      */
-    public Stream<Service> getServices(ServiceQueryParams serviceQueryParams);
+    //public Stream<Service> getServices(ServiceQueryParams serviceQueryParams);
 
     /**
      * Gets a list of all DCAE Service References that match a service type filter.
@@ -159,32 +173,8 @@ public interface InventoryClient {
      * @return Service
      */
 
-    public Optional<Service> getService(String serviceId);
-
-    /**
-     * Puts a new DCAE Service with the specified serviceId, or updates an existing
-     * DCAE Service corresponding to the specified serviceId.
-     * 
-     * @param typeId  Type ID of the associated DCAE Service Type
-     * 
-     * @param service DCAE Service to be uploaded.
-     */
-    public void putService(String typeId, Service service);
-
-    /**
-     * Deletes an existing DCAE Service object corresponding to the specified
-     * serviceId.
-     * 
-     * @param serviceId Service ID of the DCAE Service to be deleted.
-     * 
-     * @exception ServiceNotFoundException           Thrown if the DCAE Service is
-     *                                               not found.
-     * 
-     * @exception ServiceAlreadyDeactivatedException Thrown if the DCAE Service is
-     *                                               already deactivated.
-     * 
-     */
+    //public Optional<Service> getService(String serviceId);
 
-    public void deleteService(String serviceId) throws ServiceNotFoundException, ServiceAlreadyDeactivatedException;
+    public String getBaseUrl();
 
 }
index c7c1cdf..69fca94 100644 (file)
@@ -30,6 +30,7 @@ import org.apache.http.client.CredentialsProvider;
 import org.apache.http.impl.client.BasicCredentialsProvider;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClientBuilder;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList;
 import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
 import org.springframework.web.client.RestTemplate;
@@ -43,6 +44,13 @@ import org.springframework.web.client.RestTemplate;
 public class RestClientBase {
     protected RestTemplate restTemplate = null;
 
+    /**
+     * @param restTemplate the restTemplate to set
+     */
+    public void setRestTemplate(RestTemplate restTemplate) {
+        this.restTemplate = restTemplate;
+    }
+
     protected void createRestTemplate(URL url, String user, String pass, String urlScheme) {
         RestTemplate restTempl = null;
         final HttpHost httpHost = new HttpHost(url.getHost(), url.getPort(), urlScheme);
@@ -61,7 +69,9 @@ public class RestClientBase {
         HttpComponentsClientHttpRequestFactoryBasicAuth requestFactory = new HttpComponentsClientHttpRequestFactoryBasicAuth(
                 httpHost);
         requestFactory.setHttpClient(httpClient);
-
+        //requestFactory.setReadTimeout(10000);
+        //requestFactory.setConnectionRequestTimeout(2000);
+        //requestFactory.setConnectTimeout(10000);
         // Put the factory in the template
         restTempl = new RestTemplate();
         restTempl.setRequestFactory(requestFactory);
@@ -111,4 +121,16 @@ public class RestClientBase {
         headers.set("Tenant", tenant);
         return new HttpEntity<String>("parameters", headers);
     }
+
+    /**
+     * Create Http Entity for the consul token header
+     * 
+     * @param token string
+     * @return
+     */
+    protected HttpEntity<String> getConsulTokenHeader(String token) {
+        HttpHeaders headers = new HttpHeaders();
+        headers.set("X-Consul-Token", token);
+        return new HttpEntity<String>("parameters", headers);
+    }
 }
index c1296f0..100170c 100644 (file)
@@ -28,51 +28,61 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map.Entry;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.function.Predicate;
 import java.util.Optional;
-import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import javax.annotation.PostConstruct;
 
-import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceAlreadyDeactivatedException;
-import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceNotFoundException;
 import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeAlreadyDeactivatedException;
 import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException;
 import org.onap.ccsdk.dashboard.model.inventory.ApiResponseMessage;
-import org.onap.ccsdk.dashboard.model.inventory.InventoryProperty;
 import org.onap.ccsdk.dashboard.model.inventory.Link;
 import org.onap.ccsdk.dashboard.model.inventory.Service;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceGroupByResults;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceList;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceRef;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceRequest;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceType;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeList;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummaryList;
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
+import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.onap.portalsdk.core.objectcache.AbstractCacheManager;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.ParameterizedTypeReference;
-import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.ResponseEntity;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
 import org.springframework.web.client.HttpClientErrorException;
 
 @org.springframework.stereotype.Service
+@Component
 public class RestInventoryClientImpl extends RestClientBase implements InventoryClient {
-
+    private static EELFLoggerDelegate logger =
+        EELFLoggerDelegate.getLogger(RestInventoryClientImpl.class);
+    
     private String baseUrl;
     public static final String SERVICE_TYPES = "dcae-service-types";
     public static final String SERVICES = "dcae-services";
     public static final String SERVICES_GROUPBY = "dcae-services-groupby";
+    public static final String HEALTH_CHECK = "healthcheck";
 
+    /**
+     * For caching data 
+     */
+    private AbstractCacheManager cacheManager;
+    
     @PostConstruct
     public void init() {
-        String webapiUrl = DashboardProperties.getControllerProperty("dev",
-            DashboardProperties.CONTROLLER_SUBKEY_INVENTORY_URL);
+        String webapiUrl = DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_INVENTORY_URL);
         if (webapiUrl == null)
             throw new IllegalArgumentException("Null URL not permitted");
         URL url = null;
@@ -90,28 +100,74 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory
 
     }
 
-    public Stream<ServiceType> getServiceTypes() {
-        String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES }, null);
-        ResponseEntity<ServiceTypeList> response = restTemplate.exchange(url, HttpMethod.GET, null,
-                new ParameterizedTypeReference<ServiceTypeList>() {
+    public String checkHealth() {
+        String url = buildUrl(new String[] { baseUrl, HEALTH_CHECK }, null);
+        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, null,
+                new ParameterizedTypeReference<String>() {
                 });
-        Collection<ServiceType> collection = response.getBody().items;
-
+        return response.getBody();
+    }
+    
+    @Scheduled(fixedDelay=300000, initialDelay=30000)
+    public void cacheServiceTypes() {
+        logger.debug(EELFLoggerDelegate.debugLogger, "cacheServiceTypes begin");
+        String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES }, new String[] {"onlyLatest", "false"});
+        ResponseEntity<ServiceTypeSummaryList> response = restTemplate.exchange(url, HttpMethod.GET, null,
+                new ParameterizedTypeReference<ServiceTypeSummaryList>() {
+                });
+        Collection<ServiceTypeSummary> collection = response.getBody().items;
         // Continue retrieving items on the next page if they exist
         Link nextLink = response.getBody().paginationLinks.nextLink;
         while (nextLink != null) {
             url = response.getBody().paginationLinks.nextLink.href;
             response = restTemplate.exchange(url, HttpMethod.GET, null,
-                    new ParameterizedTypeReference<ServiceTypeList>() {
+                    new ParameterizedTypeReference<ServiceTypeSummaryList>() {
                     });
             collection.addAll(response.getBody().items);
             nextLink = response.getBody().paginationLinks.nextLink;
         }
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        // put into cache
+        lock.writeLock().lock();
+        getCacheManager().putObject(SERVICE_TYPES, collection);
+        lock.writeLock().unlock();
+        logger.debug(EELFLoggerDelegate.debugLogger, "cacheServiceTypes end");
+    }
 
+    public Stream<ServiceTypeSummary> getServiceTypes() {
+        String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES }, new String[] {"onlyLatest", "false"});
+        ResponseEntity<ServiceTypeSummaryList> response = restTemplate.exchange(url, HttpMethod.GET, null,
+                new ParameterizedTypeReference<ServiceTypeSummaryList>() {
+                });
+        Collection<ServiceTypeSummary> collection = response.getBody().items;
+        // Continue retrieving items on the next page if they exist
+        Link nextLink = response.getBody().paginationLinks.nextLink;
+        while (nextLink != null) {
+            url = response.getBody().paginationLinks.nextLink.href;
+            response = restTemplate.exchange(url, HttpMethod.GET, null,
+                    new ParameterizedTypeReference<ServiceTypeSummaryList>() {
+                    });
+            collection.addAll(response.getBody().items);
+            nextLink = response.getBody().paginationLinks.nextLink;
+        }
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        // put into cache
+        lock.writeLock().lock();
+        getCacheManager().putObject(SERVICE_TYPES, collection);
+        lock.writeLock().unlock();
         return collection.stream();
     }
+    
+    @Autowired
+    public void setCacheManager(AbstractCacheManager cacheManager) {
+        this.cacheManager = cacheManager;
+    }
 
-    public Stream<ServiceType> getServiceTypes(ServiceTypeQueryParams serviceTypeQueryParams) {
+    public AbstractCacheManager getCacheManager() {
+        return cacheManager;
+    }
+    
+    public Stream<ServiceTypeSummary> getServiceTypes(ServiceTypeQueryParams serviceTypeQueryParams) {
 
         // Only utilize the parameters that aren't null
         HashMap<String, String> map = new HashMap<>();
@@ -139,6 +195,12 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory
         if (serviceTypeQueryParams.getAsdcResourceId() != null) {
             map.put("asdcResourceId", serviceTypeQueryParams.getAsdcResourceId());
         }
+        if (serviceTypeQueryParams.getApplication() != null) {
+            map.put("application", serviceTypeQueryParams.getApplication());
+        }
+        if (serviceTypeQueryParams.getComponent() != null) {
+            map.put("component", serviceTypeQueryParams.getComponent());
+        }
         ArrayList<String> params = new ArrayList<>();
         for (Entry<String, String> ent : map.entrySet()) {
             params.add(ent.getKey());
@@ -146,17 +208,17 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory
         }
 
         String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES }, params.toArray(new String[params.size()]));
-        ResponseEntity<ServiceTypeList> response = restTemplate.exchange(url, HttpMethod.GET, null,
-                new ParameterizedTypeReference<ServiceTypeList>() {
+        ResponseEntity<ServiceTypeSummaryList> response = restTemplate.exchange(url, HttpMethod.GET, null,
+                new ParameterizedTypeReference<ServiceTypeSummaryList>() {
                 });
-        Collection<ServiceType> collection = response.getBody().items;
+        Collection<ServiceTypeSummary> collection = response.getBody().items;
 
         // Continue retrieving items on the next page if they exist
         Link nextLink = response.getBody().paginationLinks.nextLink;
         while (nextLink != null) {
             url = response.getBody().paginationLinks.nextLink.href;
             response = restTemplate.exchange(url, HttpMethod.GET, null,
-                    new ParameterizedTypeReference<ServiceTypeList>() {
+                    new ParameterizedTypeReference<ServiceTypeSummaryList>() {
                     });
             collection.addAll(response.getBody().items);
             nextLink = response.getBody().paginationLinks.nextLink;
@@ -170,14 +232,31 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory
 
         // Take the ServiceType object and create a ServiceTypeRequest from it
         ServiceTypeRequest serviceTypeRequest = ServiceTypeRequest.from(serviceType);
-
-        return restTemplate.postForObject(url, serviceTypeRequest, ServiceType.class);
+        ServiceType upldBp = restTemplate.postForObject(url, serviceTypeRequest, ServiceType.class);
+        List<ServiceTypeSummary> itemList = this.getServiceTypes().collect(Collectors.toList());
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        lock.writeLock().lock();
+        getCacheManager().removeObject(SERVICE_TYPES);
+        // put updated collection back into cache
+        getCacheManager().putObject(SERVICE_TYPES, itemList);
+        lock.writeLock().unlock();
+        return upldBp;
     }
 
+    @SuppressWarnings("unchecked")
     public ServiceType addServiceType(ServiceTypeRequest serviceTypeRequest) {
         String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES }, null);
-
-        return restTemplate.postForObject(url, serviceTypeRequest, ServiceType.class);
+        ServiceType uplBp = restTemplate.postForObject(url, serviceTypeRequest, ServiceType.class);
+        // update application cache with new record to refresh screen immediately
+        // query inventory for the newly uploaded entry, 
+        // using query params (typeName, owner, app, component)
+        List<ServiceTypeSummary> itemList = this.getServiceTypes().collect(Collectors.toList());
+        ReadWriteLock lock = new ReentrantReadWriteLock();
+        lock.writeLock().lock();
+        // put updated collection back into cache
+        getCacheManager().putObject(SERVICE_TYPES, itemList);
+        lock.writeLock().unlock();
+        return uplBp;
     }
 
     public Optional<ServiceType> getServiceType(String typeId) {
@@ -188,12 +267,33 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory
         return Optional.ofNullable(response.getBody());
     }
 
+    @SuppressWarnings("unchecked")
     public void deleteServiceType(String typeId)
             throws ServiceTypeNotFoundException, ServiceTypeAlreadyDeactivatedException {
         String url = buildUrl(new String[] { baseUrl, SERVICE_TYPES, typeId }, null);
+        ReadWriteLock lock = new ReentrantReadWriteLock();
         try {
-            restTemplate.exchange(url, HttpMethod.DELETE, null, new ParameterizedTypeReference<ApiResponseMessage>() {
+            ResponseEntity<ApiResponseMessage> response = 
+                restTemplate.exchange(url, HttpMethod.DELETE, null, 
+                    new ParameterizedTypeReference<ApiResponseMessage>() {
             });
+            // update the application cache
+            lock.readLock().lock();
+            List<ServiceTypeSummary> itemList = 
+                (List<ServiceTypeSummary>)getCacheManager().getObject(SERVICE_TYPES);
+            lock.readLock().unlock();
+            if (itemList == null) {
+                itemList = getServiceTypes().collect(Collectors.toList());
+            }
+            Predicate<ServiceTypeSummary> typeIdFilter =
+                p -> p.getTypeId().isPresent() && !p.getTypeId().get().equals(typeId);
+            itemList = (List<ServiceTypeSummary>)itemList.stream().filter(typeIdFilter).
+                    collect(Collectors.toList());
+            lock.writeLock().lock();
+            getCacheManager().removeObject(SERVICE_TYPES);
+            // put updated collection back into cache
+            getCacheManager().putObject(SERVICE_TYPES, itemList);
+            lock.writeLock().unlock();
         } catch (HttpClientErrorException e) {
             if (e.getStatusCode().value() == 410) {
                 throw new ServiceTypeAlreadyDeactivatedException(e.getMessage());
@@ -203,7 +303,7 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory
         }
     }
 
-    public Stream<Service> getServices() {
+/*    public Stream<Service> getServices() {
         String url = buildUrl(new String[] { baseUrl, SERVICES }, null);
         ResponseEntity<ServiceList> response = restTemplate.exchange(url, HttpMethod.GET, null,
                 new ParameterizedTypeReference<ServiceList>() {
@@ -222,7 +322,7 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory
 
         return collection.stream();
     }
-
+*/
     public ServiceRefList getServicesForType(ServiceQueryParams serviceQueryParams) {
 
         // Only utilize the typeId
@@ -257,7 +357,7 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory
 
         return new ServiceRefList(srvcRefList, itemCnt);
     }
-
+/*
     public Stream<Service> getServices(ServiceQueryParams serviceQueryParams) {
 
         // Only utilize the parameters that aren't null
@@ -308,43 +408,22 @@ public class RestInventoryClientImpl extends RestClientBase implements Inventory
         return collection.stream();
     }
 
-    /*
-     * public Set<InventoryProperty> getPropertiesOfServices(String propertyName) {
-     * String url = buildUrl(new String[] {baseUrl, SERVICES_GROUPBY, propertyName},
-     * null); ResponseEntity<ServiceGroupByResults> response =
-     * restTemplate.exchange(url, HttpMethod.GET, null, new
-     * ParameterizedTypeReference<ServiceGroupByResults>() { }); return
-     * response.getBody().propertyValues; }
-     */
     public Optional<Service> getService(String serviceId) {
         String url = buildUrl(new String[] { baseUrl, SERVICES, serviceId }, null);
-        ResponseEntity<Service> response = restTemplate.exchange(url, HttpMethod.GET, null,
-                new ParameterizedTypeReference<Service>() {
-                });
-        return Optional.ofNullable(response.getBody());
-    }
-
-    public void putService(String typeId, Service service) {
-        String url = buildUrl(new String[] { baseUrl, SERVICES, service.getServiceId() }, null);
-
-        ServiceRequest serviceRequest = ServiceRequest.from(typeId, service);
-
-        restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<ServiceRequest>(serviceRequest),
-                new ParameterizedTypeReference<Service>() {
-                });
-    }
-
-    public void deleteService(String serviceId) throws ServiceNotFoundException, ServiceAlreadyDeactivatedException {
-        String url = buildUrl(new String[] { baseUrl, SERVICES, serviceId }, null);
+        ResponseEntity<Service> response = null;
         try {
-            restTemplate.exchange(url, HttpMethod.DELETE, null, new ParameterizedTypeReference<ApiResponseMessage>() {
-            });
-        } catch (HttpClientErrorException e) {
-            if (e.getStatusCode().value() == 410) {
-                throw new ServiceAlreadyDeactivatedException(e.getMessage());
-            } else if (e.getStatusCode().value() == 404) {
-                throw new ServiceNotFoundException(e.getMessage());
-            }
+               response = restTemplate.exchange(url, HttpMethod.GET, null,
+                    new ParameterizedTypeReference<Service>() {
+                    });
+        }
+        catch(HttpClientErrorException e) {
+               return null;
         }
+        
+        return Optional.ofNullable(response.getBody());
+    }
+  */
+    public String getBaseUrl() {
+       return this.baseUrl;
     }
 }
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointService.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointService.java
deleted file mode 100644 (file)
index b63f972..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-
-package org.onap.ccsdk.dashboard.service;
-
-import java.util.List;
-
-import org.onap.ccsdk.dashboard.domain.ControllerEndpoint;
-import org.onap.ccsdk.dashboard.domain.EcdComponent;
-
-/**
- * Provides methods for managing the user's selection of controller endpoint.
- * 
- * No method throws a checked exception, in keeping with the Spring philosophy
- * of throwing unchecked exceptions.
- */
-public interface ControllerEndpointService {
-
-    /**
-     * Gets the object for the specified user ID.
-     * 
-     * @param userId Application user ID
-     * @return ControllerEndpointCredentials instance; null if none exists.
-     */
-    ControllerEndpoint getControllerEndpointSelection(long userId);
-
-    /**
-     * Creates or updates an entry for the user ID specified within the object.
-     * 
-     * @param endpoint info to store.
-     */
-    void updateControllerEndpointSelection(ControllerEndpoint endpoint);
-
-    /**
-     * Deletes the object for the specified user ID.
-     * 
-     * @param userId Application user ID
-     */
-    void deleteControllerEndpointSelection(long userId);
-
-    /**
-     * Gets all component names that are currently supported through ECOMPC
-     * dashboard
-     * 
-     * @return Component instance list;
-     */
-    public List<EcdComponent> getComponents();
-
-    /**
-     * 
-     * Add a new component to support in ECOMPC platform
-     * 
-     * @param component
-     */
-    void insertComponent(EcdComponent component);
-}
diff --git a/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointServiceImpl.java b/ccsdk-app-common/src/main/java/org/onap/ccsdk/dashboard/service/ControllerEndpointServiceImpl.java
deleted file mode 100644 (file)
index 6eacb47..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-
-package org.onap.ccsdk.dashboard.service;
-
-import org.onap.ccsdk.dashboard.domain.ControllerEndpoint;
-import org.onap.ccsdk.dashboard.domain.EcdComponent;
-
-import java.util.List;
-
-import org.onap.portalsdk.core.service.DataAccessService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-/**
- * Complete controller endpoint information is in properties. The database just
- * stores the user's selection. Users are not expected to enter credentials so
- * this hybrid solution keeps credentials out of the database.
- */
-@Service("controllerEndpointService")
-@Transactional
-public class ControllerEndpointServiceImpl implements ControllerEndpointService {
-
-    @Autowired
-    private DataAccessService dataAccessService;
-
-    /**
-     * @return Data access service
-     */
-    public DataAccessService getDataAccessService() {
-        return dataAccessService;
-    }
-
-    /**
-     * @param dataAccessService Data access service
-     */
-    public void setDataAccessService(DataAccessService dataAccessService) {
-        this.dataAccessService = dataAccessService;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.openecomp.controller.dashboard.service.ControllerEndpointService#
-     * getControllerEndpoint(java.lang.Integer)
-     */
-    @Override
-    public ControllerEndpoint getControllerEndpointSelection(long userId) {
-        return (ControllerEndpoint) getDataAccessService().getDomainObject(ControllerEndpoint.class, userId, null);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.openecomp.controller.dashboard.service.ControllerEndpointService#
-     * getComponents()
-     */
-    @SuppressWarnings("unchecked")
-    @Override
-    public List<EcdComponent> getComponents() {
-        return dataAccessService.executeNamedQuery("getAllComponents", null, null);
-    }
-
-    @Override
-    public void insertComponent(EcdComponent component) {
-        dataAccessService.saveDomainObject(component, null);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.openecomp.controller.dashboard.service.ControllerEndpointService#
-     * updateControllerEndpoint(org.openecomp.controller.dashboard.domain.
-     * ControllerEndpoint)
-     */
-    @Override
-    public void updateControllerEndpointSelection(ControllerEndpoint endpoint) {
-        getDataAccessService().saveDomainObject(endpoint, null);
-    }
-
-    /*
-     * // (non-Javadoc)
-     * 
-     * @see org.openecomp.controller.dashboard.service.ControllerEndpointService#
-     * deleteControllerEndpoint(java.lang.Integer)
-     */
-    @Override
-    public void deleteControllerEndpointSelection(long userId) {
-        ControllerEndpoint dbEntry = (ControllerEndpoint) getDataAccessService()
-                .getDomainObject(ControllerEndpoint.class, userId, null);
-        if (dbEntry != null)
-            getDataAccessService().deleteDomainObject(dbEntry, null);
-    }
-
-}
index 35d5d01..d785ea5 100644 (file)
@@ -3,8 +3,6 @@
  *
  * =================================================================================
  *  Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- *  
- *  Modifications Copyright (C) 2019 IBM.
  * ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -45,83 +43,61 @@ import org.springframework.core.env.Environment;
 public class DashboardProperties {
 
     /**
-     * Key for property that indicates if test data should be used
-     */
-    public static final String CONTROLLER_MOCK_DATA = "controller.mock.data";
-    /**
-     * Key for property with list of controllers
+     * Key for property with list of sites
      */
-    public static final String CONTROLLER_KEY_LIST = "controller.key.list";
+    public static final String CONTROLLER_SITE_LIST = "controller.site.list";
     /**
-     * Subkey for property with Controller name (description)
+     * Subkey for property with site name
      */
-    public static final String CONTROLLER_SUBKEY_NAME = "name";
+    public static final String SITE_SUBKEY_NAME = "name";
     /**
-     * Subkey for property with Controller URL
+     * Subkey for property with Cloudify URL
      */
-    public static final String CONTROLLER_SUBKEY_URL = "url";
+    public static final String SITE_SUBKEY_CLOUDIFY_URL = "cloudify.url";
     /**
      * Subkey for property with Inventory URL
      */
-    public static final String CONTROLLER_SUBKEY_INVENTORY_URL = "inventory.url";
+    public static final String SITE_SUBKEY_INVENTORY_URL = "inventory.url";
     /**
      * Subkey for property with Deployment Handler URL
      */
-    public static final String CONTROLLER_SUBKEY_DHANDLER_URL = "dhandler.url";
+    public static final String SITE_SUBKEY_DHANDLER_URL = "dhandler.url";
     /**
      * Subkey for property with Consul URL
      */
-    public static final String CONTROLLER_SUBKEY_CONSUL_URL = "consul.url";
+    public static final String SITE_SUBKEY_CONSUL_URL = "consul.url";
+    /**
+     * Subkey for property with DBCL URL
+     */
+    public static final String SITE_SUBKEY_DBCL_URL = "dbcl.url";
+    /**
+     * Subkey for property with DBCL URL
+     */
+    public static final String SITE_SUBKEY_FEED_URL = "feed_m.url";
     /**
      * Subkey for property with Controller user name for authentication
      */
-    public static final String CONTROLLER_SUBKEY_USERNAME = "username";
+    public static final String SITE_SUBKEY_CLOUDIFY_USERNAME = "cloudify.username";
     /**
      * Subkey for property with Controller password
      */
-    public static final String CONTROLLER_SUBKEY_PASS = "password";
+    public static final String SITE_SUBKEY_CLOUDIFY_PASS = "cloudify.password";
     /**
      * Subkey for property with Controller password encryption status
      */
-    public static final String CONTROLLER_SUBKEY_ENCRYPTED = "is_encrypted";
+    public static final String SITE_SUBKEY_CLOUDIFY_ENCRYPTED = "is_encrypted";
+    
     /**
      * Key for dashboard deployment environment - dev/uat/prod
      */
     public static final String CONTROLLER_IN_ENV = "controller.env";
 
-    /**
-     * Key for cloudify tenant environment
-     */
-    public static final String CLOUDIFY_TENANT_PRIM = "cloudify.tenant.primary";
-
-    /**
-     * Key for aic tenant environment
-     */
-    public static final String AIC_TENANT_PRIM = "aic.tenant.primary";
-
-    /**
-     * Key for controller type: ATT or OS
-     */
-    public static final String CONTROLLER_TYPE = "controller.type";
-
     /**
      * Key for K8s deploy permission string
      * 
      */
     public static final String APP_K8S_PERM = "k8s.deploy.perm";
 
-    public static final String OPS_K8S_URL = "ops.k8s.url";
-
-    public static final String OPS_GRAFANA_URL = "ops.grf.url";
-
-    public static final String OPS_CLOUDIFY_URL = "ops.cfy.url";
-
-    public static final String OPS_CONSUL_URL = "ops.cnsl.url";
-
-    public static final String OPS_PROMETHEUS_URL = "ops.prom.url";
-
-    public static final String OPS_DBCL_URL = "ops.dbcl.url";
-
     private static Environment environment;
 
     protected Environment getEnvironment() {
@@ -133,7 +109,7 @@ public class DashboardProperties {
      */
     @Autowired
     public void setEnvironment(final Environment environment) {
-        DashboardProperties.environment = environment;
+        this.environment = environment;
     }
 
     /**
@@ -180,8 +156,8 @@ public class DashboardProperties {
         String listVal = getProperty(key);
         if (listVal == null)
             return null;
-        
-        return listVal.split("\\s*,\\s*");
+        String[] vals = listVal.split("\\s*,\\s*");
+        return vals;
     }
 
     /**
@@ -197,4 +173,16 @@ public class DashboardProperties {
         return getProperty(key);
     }
 
+    /**
+     * Convenience method to get a property from the fake hierarchical key-value
+     * set.
+     * 
+     * @param controllerKey First part of key
+     * @param propKey       Second part of key
+     * @return Property value for key "controllerKey.propKey"
+     */
+    public static String getControllerPropertyDef(final String controllerKey, final String propKey, String defVal) {
+        final String key = controllerKey + '.' + propKey;
+        return getPropertyDef(key, defVal);
+    }
 }
diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/api/controller/NbApiControllerTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/api/controller/NbApiControllerTest.java
new file mode 100644 (file)
index 0000000..3c33bda
--- /dev/null
@@ -0,0 +1,818 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+
+package org.onap.ccsdk.api.controller;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Stream;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.onap.ccsdk.dashboard.core.MockUser;
+import org.onap.ccsdk.dashboard.core.MockitoTestSuite;
+import org.onap.ccsdk.dashboard.exceptions.BadRequestException;
+import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException;
+import org.onap.ccsdk.dashboard.exceptions.DownstreamException;
+import org.onap.ccsdk.dashboard.exceptions.ServerErrorException;
+import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException;
+import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException;
+import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceId;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList;
+import org.onap.ccsdk.dashboard.model.consul.ConsulDeploymentHealth;
+import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth;
+import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentInput;
+import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest;
+import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse;
+import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponseLinks;
+import org.onap.ccsdk.dashboard.model.inventory.Service;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceList;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceRef;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceType;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeList;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummaryList;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeUploadRequest;
+import org.onap.ccsdk.dashboard.rest.CloudifyClient;
+import org.onap.ccsdk.dashboard.rest.ConsulClient;
+import org.onap.ccsdk.dashboard.rest.DeploymentHandlerClient;
+import org.onap.ccsdk.dashboard.rest.InventoryClient;
+import org.onap.portalsdk.core.domain.User;
+import org.onap.portalsdk.core.util.CacheManager;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.client.HttpStatusCodeException;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+
+@RunWith(PowerMockRunner.class)
+public class NbApiControllerTest extends MockitoTestSuite {
+
+    @Mock
+    InventoryClient inventoryClient;
+
+    @Mock
+    DeploymentHandlerClient deploymentHandlerClient;
+
+    @Mock
+    CloudifyClient cfyClient;
+
+    @Mock
+    ConsulClient consulClient;
+
+    @Mock
+    ServletUriComponentsBuilder uriBuilder;
+    
+    @InjectMocks
+    NbApiController subject = new NbApiController();
+    
+    private HttpStatusCodeException httpException =
+        new HttpServerErrorException(HttpStatus.BAD_GATEWAY);
+
+    protected final ObjectMapper objectMapper = new ObjectMapper();
+
+    HttpServletRequest mockedRequest;
+    HttpServletResponse mockedResponse;
+
+    MockUser mockUser = new MockUser();
+    ServiceList deplList = null;
+    Service deplItem = null;
+
+
+    ServiceTypeSummary bpItem, bpItem2 = null;
+    ServiceTypeSummaryList bpList, bpList2 = null;
+    ServiceType bpItemFull = null;
+    ServiceTypeList bpItemFullList = null;
+    ServiceTypeRequest bpUploadItem = null;
+
+    BadRequestException badReqError;
+    ServiceAlreadyExistsException srvcExistError;
+    ServerErrorException serverError;
+    DownstreamException downStrmError;
+    JsonProcessingException jsonError;
+    DeploymentNotFoundException notFoundError;
+    private ServiceTypeNotFoundException serviceTypeException =
+        new ServiceTypeNotFoundException("Invalid blueprint");
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        objectMapper.registerModule(new Jdk8Module());
+        getExpectedDeployments();
+        getExpectedBueprints();
+        createBpUploadItem();
+        mockedRequest = getMockedRequest();
+        mockedResponse = getMockedResponse();
+        badReqError = new BadRequestException("bad request");
+        srvcExistError = new ServiceAlreadyExistsException("service already exists");
+        serverError = new ServerErrorException("Error occured in server");
+        downStrmError = new DownstreamException("error occured in downstream");
+        notFoundError = new DeploymentNotFoundException("item not found");
+        CacheManager testCache = new CacheManager();
+        subject.setCacheManager(testCache); 
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        StringBuffer urlBuff = new StringBuffer();
+        urlBuff.append("http://orcl.com");
+        //Mockito.when(mockedRequest.getRemoteUser()).thenReturn("tester");
+        Mockito.when(mockedRequest.getRequestURL()).thenReturn(urlBuff);
+    }
+
+    public void getExpectedDeployments()
+        throws JsonParseException, JsonMappingException, IOException {
+
+        deplItem = new Service("dcae_dtiapi_1902", null, "1552335532348", "1552335532348", null,
+            "dummyVnfId", null, "dummyVnfType", "dummyLocation", "dcae_dtiapi_1902", null);
+        Collection<Service> items = new ArrayList<Service>();
+        items.add(deplItem);
+
+        String pageLinks =
+            "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}";
+        ServiceList.PaginationLinks paginationLinks =
+            objectMapper.readValue(pageLinks, ServiceList.PaginationLinks.class);
+        int totalCount = 1;
+        deplList = new ServiceList(items, totalCount, paginationLinks);
+
+    }
+
+    public void getExpectedBueprints()
+        throws JsonParseException, JsonMappingException, IOException {
+       
+        /*bpItem = new ServiceTypeSummary.Builder().application("DCAE").component("dcae").
+        typeName("xyz1731-helm-1906").owner("xyz1731").typeVersion(1906).build();*/
+        
+        bpItem = new ServiceTypeSummary("xyz1730", "xyz1730-helm-1905", 1905, "DCAE", "dcae", "123-456-321",
+            "342343", true);
+        
+        bpItem2 = new ServiceTypeSummary("xyz1731", "xyz1731-helm-1906", 1906, "DCAE", "dcae", "123-456-789",
+            "342343", true);
+        bpItemFull = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906,
+            "tosca_definitions_version: cloudify_dsl_1_3", "", "DCAE", "dcae").build();
+
+        Collection<ServiceTypeSummary> items = new ArrayList<ServiceTypeSummary>();
+        items.add(bpItem);
+
+        Collection<ServiceTypeSummary> items2 = new ArrayList<ServiceTypeSummary>();
+        items2.add(bpItem2);
+        
+        String pageLinks2 =
+            "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}";
+        ServiceTypeSummaryList.PaginationLinks paginationLinks =
+            objectMapper.readValue(pageLinks2, ServiceTypeSummaryList.PaginationLinks.class);
+        int totalCount = 1;
+        bpList = new ServiceTypeSummaryList(items, totalCount, paginationLinks);
+        bpList2 = new ServiceTypeSummaryList(items2, totalCount, paginationLinks);
+        
+    }
+
+    public void createBpUploadItem() {
+        bpUploadItem = ServiceTypeRequest.from(bpItemFull);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public final void testCreateBlueprint() throws Exception {
+        String bpTemplate = "tosca_definitions_version: cloudify_dsl_1_3";
+        ServiceTypeUploadRequest bpUploadReq = 
+            new ServiceTypeUploadRequest("dcae_user", "mod1", 2008, bpTemplate, "DCAE", "dcae");
+        
+        when(inventoryClient.addServiceType(Matchers.<ServiceTypeRequest>any()))
+        .thenThrow(BlueprintParseException.class).thenThrow(httpException)
+        .thenThrow(Exception.class).thenReturn(bpItemFull);
+        
+        //when(mockedRequest.getRequestURI()).thenReturn("https://invt-svc:8080/dcae-service-types");
+        String actual = subject.createBlueprint(mockedRequest, mockedResponse, bpUploadReq, uriBuilder);
+        assertTrue(actual.contains("error"));
+        actual = subject.createBlueprint(mockedRequest, mockedResponse, bpUploadReq, uriBuilder);
+        assertTrue(actual.contains("error"));
+        actual = subject.createBlueprint(mockedRequest, mockedResponse, bpUploadReq, uriBuilder);
+        assertTrue(actual.contains("error"));
+        actual = subject.createBlueprint(mockedRequest, mockedResponse, bpUploadReq, uriBuilder);
+        assertTrue(actual.contains("xyz"));
+    }
+    
+    @Test
+    public final void testCreateBlueprint_badReq() throws Exception {
+        String bpTemplate = "tosca_definitions_version: cloudify_dsl_1_3";
+        ServiceTypeUploadRequest bpUploadReq = 
+            new ServiceTypeUploadRequest("dcae_user", "mod1", 2008, bpTemplate, "DCAE", "");
+        
+        when(inventoryClient.addServiceType(Matchers.<ServiceTypeRequest>any()))
+        .thenThrow(BlueprintParseException.class).thenThrow(httpException)
+        .thenThrow(Exception.class).thenReturn(null);
+        
+        String actual = subject.createBlueprint(mockedRequest, mockedResponse, bpUploadReq, uriBuilder);
+        assertTrue(actual.contains("error"));
+    }
+    
+    @Test
+    public final void testQueryBlueprint() throws Exception {
+        
+        Optional<ServiceType> optionBp = Optional.ofNullable(bpItemFull);
+        when(inventoryClient.getServiceType(Mockito.any())).thenReturn(optionBp).thenThrow(Exception.class);
+        
+        String actual = subject.queryBlueprint("123-343", mockedRequest, mockedResponse, uriBuilder);
+        assertTrue(actual.contains("xyz"));
+        
+        actual = subject.queryBlueprint("123-343", mockedRequest, mockedResponse, uriBuilder);
+        assertTrue(actual.contains("error"));
+    }
+    
+    @Test
+    public final void testGetTenants() throws Exception {
+        String tenantsList =
+            "{\"items\": [{\"id\": 1, \"name\": \"default_tenant\", \"dName\": \"default_tenant\" }, "
+                + "{\"id\": 2, \"name\": \"dyh1b1902\", \"dName\": \"dyh1b1902\"}], "
+                + "\"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}";
+        CloudifyTenantList sampleData = null;
+        try {
+            sampleData = objectMapper.readValue(tenantsList, CloudifyTenantList.class);
+        } catch (Exception e) {
+        }
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+
+        Mockito.when(cfyClient.getTenants()).thenReturn(sampleData);
+
+        String tenantStr = subject.getTenants(mockedRequest);
+        assertTrue(tenantStr.contains("dyh1b"));
+    }
+    
+    @Test
+    public final void testGetBlueprintsByPage() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        String filterStr = "{\"owner\": \"xyz1730\", \"name\": \"xyz1730-helm-1905\", \"id\": \"123\"}";
+       
+        mockedRequest.addParameter("filters", filterStr);
+        mockedRequest.addParameter("sort", "name");
+
+        Set<String> userRoleSet = new HashSet<String>();
+        Set<String> userApps = new TreeSet<>();
+        userRoleSet.add("Standard User");
+        userRoleSet.add("ECOMPC_DCAE_WRITE");
+        userApps.add("dcae");
+        
+        Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet);
+        Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps);
+
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1).thenThrow(Exception.class);
+        String result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(result.contains("xyz")); 
+        
+        result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(result.contains("error"));
+    }
+    
+    @Test
+    public final void testGetBlueprintsByPage_sortByOwner() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        mockedRequest.addParameter("sort", "owner");
+
+        Set<String> userRoleSet = new HashSet<String>();
+        Set<String> userApps = new TreeSet<>();
+        userRoleSet.add("Standard User");
+        userRoleSet.add("ECOMPC_DCAE_WRITE");
+        userApps.add("dcae");
+        
+        Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet);
+        Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps);
+
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1).thenThrow(Exception.class);
+        String result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(result.contains("xyz")); 
+        
+        result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(result.contains("error"));
+    }
+    
+    @Test
+    public final void testGetBlueprintsByPage_sortByTypeId() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        mockedRequest.addParameter("sort", "typeId");
+
+        Set<String> userRoleSet = new HashSet<String>();
+        Set<String> userApps = new TreeSet<>();
+        userRoleSet.add("Standard User");
+        userRoleSet.add("ECOMPC_DCAE_WRITE");
+        userApps.add("dcae");
+        
+        Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet);
+        Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps);
+
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1).thenThrow(Exception.class);
+        String result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(result.contains("xyz")); 
+        
+        result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(result.contains("error"));
+    }
+    
+    @Test
+    public final void testGetBlueprintsByPage_sortByCreated() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        mockedRequest.addParameter("sort", "created");
+
+        Set<String> userRoleSet = new HashSet<String>();
+        Set<String> userApps = new TreeSet<>();
+        userRoleSet.add("Standard User");
+        userRoleSet.add("ECOMPC_DCAE_WRITE");
+        userApps.add("dcae");
+        
+        Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet);
+        Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps);
+
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1).thenThrow(Exception.class);
+        String result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(result.contains("xyz")); 
+        
+        result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(result.contains("error"));
+    }
+    
+    @Test
+    public final void testGetBlueprintsByPage_sortByVersion() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        mockedRequest.addParameter("sort", "typeVersion");
+
+        Set<String> userRoleSet = new HashSet<String>();
+        Set<String> userApps = new TreeSet<>();
+        userRoleSet.add("Standard User");
+        userRoleSet.add("ECOMPC_DCAE_WRITE");
+        userApps.add("dcae");
+        
+        Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet);
+        Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps);
+
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1).thenThrow(Exception.class);
+        String result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(result.contains("xyz")); 
+        
+        result = subject.getBlueprintsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(result.contains("error"));
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Test
+    public final void testGetDeployment() {
+        CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1");
+
+        List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>();
+        items.add(cldDepl);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata);
+
+        when(cfyClient.getDeployment(Mockito.any())).thenReturn(cldDeplList).thenThrow(Exception.class);
+        
+        String actual = subject.getDeployment("id1", mockedRequest);
+        assertTrue(actual.contains("id1"));
+        
+        actual = subject.getDeployment("id1", mockedRequest);
+        assertTrue(actual.contains("error"));
+    }
+    
+    @Test
+    public final void testGetDeploymentsByPage() throws Exception {
+        CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1");
+
+        List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>();
+        items.add(cldDepl);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata);
+
+        when(cfyClient.getDeploymentsWithFilter(Mockito.any())).thenReturn(items).thenThrow(Exception.class);
+        
+        String actual = subject.getDeploymentsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(actual.contains("id1"));
+        
+        actual = subject.getDeploymentsByPage(mockedRequest, 1, 1, uriBuilder, mockedResponse);
+        assertTrue(actual.contains("error"));
+    }
+    
+    @Test
+    public final void testGetDeploymentInputs() throws Exception {
+        CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1");
+
+        List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>();
+        items.add(cldDepl);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata);
+
+        when(cfyClient.getDeploymentInputs(Mockito.any(), Mockito.any())).thenReturn(cldDeplList).thenThrow(httpException).thenThrow(Exception.class);
+        
+        String actual = subject.getDeploymentInputs("dep_id", "tenant1", mockedRequest);
+        assertTrue(actual.contains("id1"));
+
+        actual = subject.getDeploymentInputs("dep_id", "tenant1", mockedRequest);
+        assertTrue(actual.contains("error"));
+
+        actual = subject.getDeploymentInputs("dep_id", "tenant1", mockedRequest);
+        assertTrue(actual.contains("error"));
+
+    }
+    
+    @Test
+    public final void testGetServicesForType() throws Exception {
+        String testTypeIds = "44234234";
+        ServiceRef expectedSrvc = new ServiceRef("dcae_dtiapi_1902", "432423", "433434");
+        Collection<ServiceRef> expectedSrvcIds = new ArrayList<ServiceRef>();
+        expectedSrvcIds.add(expectedSrvc);
+        ServiceRefList expectedSrvcRefList = new ServiceRefList(expectedSrvcIds, 1);
+
+        when(inventoryClient.getServicesForType(Matchers.<ServiceQueryParams>any()))
+            .thenReturn(expectedSrvcRefList);
+        String actual = subject.getServicesForType(mockedRequest, testTypeIds);
+        assertTrue(actual.contains(testTypeIds));
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Test
+    public final void testCreateDeployment() throws Exception {
+        Map<String, Object> inputs = new HashMap<>();
+        inputs.put("key1", "value1");
+        inputs.put("key2", "value2");
+        inputs.put("key3", "value3");
+        inputs.put("key4", 100);
+
+        DeploymentInput deployInput1 = new DeploymentInput("component1", "tag1",
+            "xyz1731-helm-1906", 1906, "blueprintId", inputs, "tenant1", 
+            null, true, true, true, false, true, false);
+
+        DeploymentInput deployInput2 = new DeploymentInput("component1", "tag1",
+            "xyz1731-helm-1906", 1906, null, inputs, "tenant1",
+            null, true, true, true, false, true, false);
+
+        DeploymentResponseLinks expectLink = new DeploymentResponseLinks("self", "status");
+        DeploymentResponse expectResp = new DeploymentResponse("req1", expectLink);
+
+        Collection<ServiceTypeSummary> items = bpList2.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
+            .thenReturn(sampleStream1);
+
+/*        String actualResp0 = subject.createDeployment(mockedRequest, mockedResponse, deployInput2);
+        assertTrue(actualResp0.contains("error"));*/
+
+        Optional<ServiceType> optionBp = Optional.ofNullable(bpItemFull);
+        Mockito.when(inventoryClient.getServiceType(Matchers.anyString())).thenReturn(optionBp);
+        
+        StringBuffer expectedStrBuff = new StringBuffer();
+        expectedStrBuff.append("http://oom.s2.com");
+        when(mockedRequest.getRequestURL()).thenReturn(expectedStrBuff);
+
+        when(deploymentHandlerClient.putDeployment(Matchers.anyString(), Matchers.anyString(),
+            Matchers.<DeploymentRequest>any())).thenReturn(expectResp).thenReturn(expectResp)
+                .thenThrow(badReqError)
+                .thenThrow(srvcExistError).thenThrow(serverError).thenThrow(downStrmError)
+                .thenThrow(Exception.class);
+
+        String actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1);
+        assertTrue(actualResp.contains("component1"));
+        
+        actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput2);
+        assertTrue(actualResp.contains("component1"));
+
+        actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1);
+        assertTrue(actualResp.contains("error"));
+
+        actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1);
+        assertTrue(actualResp.contains("error"));
+
+        actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1);
+        assertTrue(actualResp.contains("error"));
+
+        actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1);
+        assertTrue(actualResp.contains("error"));
+
+        actualResp = subject.createDeployment(mockedRequest, mockedResponse, deployInput1);
+        assertTrue(actualResp.contains("error"));
+
+    }
+    
+    @Test
+    public final void testGetExecutionByDeploymentId() throws Exception {
+        CloudifyExecution cldExecution =
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
+        
+        List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
+
+        cldExecutionList.add(cldExecution);
+
+        CloudifyExecutionList cloudifyExecutionList =
+            new CloudifyExecutionList(cldExecutionList, null);
+        
+        when(cfyClient.getExecutionsSummary(Mockito.any(), Mockito.any()))
+            .thenReturn(cloudifyExecutionList).thenThrow(httpException).thenThrow(Exception.class);;
+        
+        String actual = subject.getExecutionByDeploymentId("deploymentId", "tenant", mockedRequest);
+        assertTrue(actual.contains("execution_id1"));
+        
+        actual = subject.getExecutionByDeploymentId("deploymentId", "tenant", mockedRequest);
+        assertTrue(actual.contains("error"));
+        
+        actual = subject.getExecutionByDeploymentId("deploymentId", "tenant", mockedRequest);
+        assertTrue(actual.contains("error"));
+
+    }
+    
+    @Test
+    public final void testGetServiceHealthByDeploymentId() throws Exception {
+        String[] svcTags = {"cfytenantname=onap"}; 
+        ConsulServiceHealth consulSrvcHlth = new ConsulServiceHealth("cjlvmcnsl00",
+            "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing",
+            "This is a pgaas1_Service_ID health check",
+            "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n",
+            "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395);
+        
+        ConsulDeploymentHealth cnslDeployHlth = 
+            new ConsulDeploymentHealth.Builder(consulSrvcHlth).build();
+        
+        when(consulClient.getServiceHealthByDeploymentId(Mockito.any())).thenReturn(cnslDeployHlth)
+            .thenThrow(httpException).thenThrow(Exception.class);
+
+        String actual = subject.getServiceHealthByDeploymentId("deploymentId", mockedRequest);
+        assertTrue(actual.contains("cjlvmcnsl00"));
+        
+        actual = subject.getServiceHealthByDeploymentId("deploymentId", mockedRequest);
+        assertTrue(actual.contains("error"));
+        
+        actual = subject.getServiceHealthByDeploymentId("deploymentId", mockedRequest);
+        assertTrue(actual.contains("error"));
+    }
+    
+    @Test
+    public final void testDeleteBlueprint() throws Exception {
+        //String expected = "{\"202\": \"OK\"}";
+        String expected = "{\"204\": \"Blueprint deleted\"}";
+        List<CloudifyDeployedTenant> deplForBp = new ArrayList<>();
+        deplForBp.clear();
+        Mockito.when(cfyClient.getDeploymentForBlueprint(Matchers.<String>any()))
+        .thenReturn(deplForBp);
+        
+        Optional<ServiceType> optionBp = Optional.ofNullable(bpItemFull);
+        Mockito.when(inventoryClient.getServiceType(Matchers.anyString())).thenReturn(optionBp);
+
+        List<ServiceRef> srvcRefList = new ArrayList<>();
+        srvcRefList.clear();
+        int itemCnt = 0;
+        ServiceRefList mockSvcRefList = new ServiceRefList(srvcRefList, itemCnt);
+
+        Mockito.when(inventoryClient.getServicesForType(Matchers.<ServiceQueryParams>any()))
+            .thenReturn(mockSvcRefList);
+        
+        doNothing().doThrow(serviceTypeException).doThrow(Exception.class).when(inventoryClient)
+            .deleteServiceType(Matchers.anyString());
+
+        String actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse, uriBuilder);
+        assertEquals(expected, actual);
+
+        actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse, uriBuilder);
+        assertTrue(actual.contains("error"));
+
+        actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse, uriBuilder);
+        assertTrue(actual.contains("error"));
+    }
+
+    @Test
+    public final void testDeleteBlueprint_withDepl() throws Exception {
+        CloudifyDeployedTenant mockCfyDeplTen = 
+            new CloudifyDeployedTenant("id1", "tenant", "45435435", "54543534");
+        
+        Optional<ServiceType> optionBp = Optional.ofNullable(bpItemFull);
+        Mockito.when(inventoryClient.getServiceType(Matchers.anyString())).thenReturn(optionBp);
+        
+        List<CloudifyDeployedTenant> deplForBp = new ArrayList<>();
+        deplForBp.add(mockCfyDeplTen);
+        Mockito.when(cfyClient.getDeploymentForBlueprint(Matchers.<String>any()))
+        .thenReturn(deplForBp);
+        
+        String actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse, uriBuilder);
+        assertTrue(actual.contains("error"));
+    }
+    
+    @Test
+    public final void testDeleteDeployment() throws Exception {
+        CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "dcae_dep_id", null, null, null, null, null, null, null, "tenant1");
+
+        List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>();
+        items.add(cldDepl);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata);
+
+        Mockito.when(cfyClient.getDeployment(Matchers.anyString(), Matchers.anyString())).thenReturn(cldDeplList);
+        
+        doNothing().doThrow(badReqError).doThrow(serverError).doThrow(downStrmError)
+        .doThrow(notFoundError).doThrow(Exception.class).when(deploymentHandlerClient)
+        .deleteDeployment(Matchers.anyString(), Matchers.anyString());
+
+        String actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse);
+        assertTrue(actual.contains("dcae_dep_id"));
+    
+        actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse);
+        assertTrue(actual.contains("error"));
+    
+        actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse);
+        assertTrue(actual.contains("error"));
+    
+        actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse);
+        assertTrue(actual.contains("error"));
+    
+        actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse);
+        assertTrue(actual.contains("error"));
+    
+        actual = subject.deleteDeployment("dcae_dep_id", mockedRequest, "tenant1", mockedResponse);
+        assertTrue(actual.contains("error"));
+
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testCancelExecution() throws Exception {
+        List<String> tenants = new ArrayList<String>();
+        tenants.add("tenant1");
+
+        HttpHeaders httpHeader = new HttpHeaders();
+        httpHeader.put("tenant", tenants);
+
+        CloudifyExecution cfyExecObj =
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
+
+        when(cfyClient.cancelExecution(Mockito.any(), Mockito.any(), Mockito.any()))
+            .thenReturn(cfyExecObj).thenThrow(Exception.class).thenThrow(httpException);
+
+        String actualResult =
+            subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse);
+        assertTrue(actualResult.contains("execution_id1"));
+
+        actualResult =
+            subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse);
+        assertTrue(actualResult.contains("error"));
+
+        actualResult =
+            subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse);
+        assertTrue(actualResult.contains("error"));
+    }
+    
+    @SuppressWarnings("unchecked")
+    @Test
+    public final void testModifyDeployment() throws Exception {
+        CloudifyExecution cldExecution =
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
+
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("tenant", "tenant1");
+        params.put("workflow", "upgrade");
+
+        CloudifyExecutionRequest cfyExecReq = new CloudifyExecutionRequest("deployment_id",
+            "upgrade", false, false, "tenant1", params);
+        
+        CloudifyNodeInstanceId cfyNodeInst = new CloudifyNodeInstanceId("node_instance_id1");
+
+        List<CloudifyNodeInstanceId> cfyNodeInstItems = new ArrayList<CloudifyNodeInstanceId>();
+
+        cfyNodeInstItems.add(cfyNodeInst);
+
+        CloudifyNodeInstanceIdList cfyNodeInstList =
+            new CloudifyNodeInstanceIdList(cfyNodeInstItems, null);
+
+        when(cfyClient.getNodeInstanceId(Mockito.any(), Mockito.any())).thenReturn(cfyNodeInstList);
+        
+        String secretTokenStr =
+            "{\"created_at\": \"created_ts\", \"key\": \"acl_key\", \"updated_at\": \"updated_ts\", \"value\": \"acl_token_val\", \"visibility\": \"global\", \"is_hidden_value\": \"false\", \"tenant_name\": \"tenant\", \"resource_availability\": \"rsrc\"}";          
+        CloudifySecret secretData = null;
+        try {
+            secretData = objectMapper.readValue(secretTokenStr, CloudifySecret.class);
+        } catch (Exception e) {
+            
+        }
+        when(cfyClient.getSecret(Mockito.any(), Mockito.any())).thenReturn(secretData);
+        when(cfyClient.startExecution(Matchers.<CloudifyExecutionRequest>any()))
+            .thenReturn(cldExecution).thenThrow(Exception.class).thenThrow(httpException);
+
+        String inputParamStr = "{\"tenant\": \"tenant1\", \"workflow\":\"upgrade\"}";
+
+        InputStream is1 = new ByteArrayInputStream(inputParamStr.getBytes());
+        String actualResult = subject.modifyDeployment("depId", mockedRequest, is1);
+        assertTrue(actualResult.contains("execution_id1"));
+
+        InputStream is2 = new ByteArrayInputStream(inputParamStr.getBytes());       
+        actualResult = subject.modifyDeployment("depId", mockedRequest, is2);
+        assertTrue(actualResult.contains("error"));
+
+        InputStream is3 = new ByteArrayInputStream(inputParamStr.getBytes());
+        actualResult = subject.modifyDeployment("depId", mockedRequest, is3);
+        assertTrue(actualResult.contains("error"));
+
+    }
+
+}
index d6e1fb0..d88e530 100644 (file)
 
 package org.onap.ccsdk.dashboard.controller;
 
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.when;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
 import org.mockito.Matchers;
 import org.mockito.Mock;
@@ -39,39 +45,51 @@ import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.onap.ccsdk.dashboard.core.MockUser;
 import org.onap.ccsdk.dashboard.core.MockitoTestSuite;
-import org.onap.ccsdk.dashboard.model.CloudifyBlueprint;
-import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenant;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployment;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateResponse;
-import org.onap.ccsdk.dashboard.model.CloudifyEvent;
-import org.onap.ccsdk.dashboard.model.CloudifyEventList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecution;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstance;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceId;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceList;
-import org.onap.ccsdk.dashboard.model.CloudifyTenant;
-import org.onap.ccsdk.dashboard.model.CloudifyTenantList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprint;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprintList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentExt;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentHelm;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEvent;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstance;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceId;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPlugin;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPluginList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceRef;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList;
 import org.onap.ccsdk.dashboard.rest.CloudifyClient;
+import org.onap.ccsdk.dashboard.rest.InventoryClient;
 import org.onap.portalsdk.core.domain.User;
+import org.onap.portalsdk.core.util.CacheManager;
 import org.onap.portalsdk.core.web.support.UserUtils;
+import org.powermock.modules.junit4.PowerMockRunner;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.client.HttpClientErrorException;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
 
+@RunWith(PowerMockRunner.class)
 public class CloudifyControllerTest extends MockitoTestSuite {
 
     @Mock
     private CloudifyClient restClient;
+    
+    @Mock
+    private InventoryClient invClient;
 
     @InjectMocks
     private CloudifyController subject = new CloudifyController();
@@ -93,6 +111,8 @@ public class CloudifyControllerTest extends MockitoTestSuite {
         MockitoAnnotations.initMocks(this);
         objectMapper.registerModule(new Jdk8Module());
         httpException = new HttpClientErrorException(HttpStatus.BAD_REQUEST, "statusText");
+        CacheManager testCache = new CacheManager();
+        subject.setCacheManager(testCache); 
     }
 
     @SuppressWarnings("unchecked")
@@ -125,6 +145,409 @@ public class CloudifyControllerTest extends MockitoTestSuite {
         assertTrue(tenantStr.contains("error"));
     }
 
+    @Test
+    public final void testGetAllServiceNames() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        //mockedRequest.addParameter("searchBy", "xyz");
+        mockedRequest.addParameter("sortBy", "owner");
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
+        
+        CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1");
+
+        List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>();
+        items.add(cldDepl);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata);
+        
+        Mockito.when(restClient.getDeployments(
+            Mockito.any(),Mockito.anyInt(), Mockito.anyInt(), Mockito.anyBoolean()))
+            .thenReturn(items);
+        
+        String actual = subject.getAllServiceNames(mockedRequest);
+        assertTrue(actual.contains("id1"));
+    }
+    @Test
+    public final void testGetDeploymentsByPage() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        mockedRequest.addParameter("searchBy", "tenant:default_tenant;cache:false;serviceRef:id1");
+        mockedRequest.addParameter("sortBy", "owner");
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
+        
+        CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1");
+
+        List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>();
+        items.add(cldDepl);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata);
+        Mockito.when(restClient.getDeployments(
+            Mockito.any(),Mockito.anyInt(), Mockito.anyInt(), Mockito.anyBoolean(), Mockito.anyBoolean()))
+            .thenReturn(items);
+        List<CloudifyDeploymentExt> cfyDepExList = 
+            new ArrayList<CloudifyDeploymentExt>();
+        List<CloudifyDeploymentHelm> cfyDeplHelmList = 
+            new ArrayList<CloudifyDeploymentHelm>();
+        
+        Mockito.when(restClient.updateWorkflowStatus(Mockito.any())).
+        thenReturn(cfyDepExList);
+        Mockito.when(restClient.updateHelmInfo(Mockito.any())).
+        thenReturn(cfyDeplHelmList);
+        
+        String actual = subject.getDeploymentsByPage(mockedRequest);
+        assertTrue(actual.contains("id1"));
+    }
+    
+    @Test
+    public final void testViewBlueprintContentById() throws Exception {
+        byte[] result = "sample blueprint yaml content".getBytes();
+        
+        when(restClient.viewBlueprint(Mockito.any(), Mockito.any())).thenReturn(result);
+        
+        byte[] actual = subject.viewBlueprintContentById("id", "tenant", mockedRequest);
+        assertArrayEquals(result, actual);
+    }
+    
+    @Test
+    public final void testGetDepCount() throws Exception {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        //mockedRequest.addParameter("searchBy", "xyz");
+        mockedRequest.addParameter("sortBy", "owner");
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
+        
+        CloudifyDeployment cldDepl = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "id1", null, null, null, null, null, null, null, "tenant1");
+
+        List<CloudifyDeployment> items = new ArrayList<CloudifyDeployment>();
+        items.add(cldDepl);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeplList = new CloudifyDeploymentList(items, metadata);
+        
+        Mockito.when(restClient.getDeploymentsWithFilter(Mockito.any()))
+            .thenReturn(items);
+        
+        String actual = subject.getDepCount(mockedRequest);
+        assertTrue(actual.contains("items"));
+    }
+    
+    @Test
+    public final void testGetPluginCount() throws JsonProcessingException {
+        CloudifyPlugin sampleData = 
+            new CloudifyPlugin("plugin1", "202001", "linux", "linux_k8s_plugin", "20200801");
+
+        List<CloudifyPlugin> cfyPlugins = new ArrayList<CloudifyPlugin>();
+        cfyPlugins.add(sampleData);
+
+        CloudifyPluginList.Metadata.Pagination pageObj =
+            new CloudifyPluginList.Metadata.Pagination(1, 0, 1);
+        CloudifyPluginList.Metadata metadata = new CloudifyPluginList.Metadata(pageObj);
+
+        CloudifyPluginList cfyPluginList = new CloudifyPluginList(cfyPlugins, metadata);
+    
+        when(restClient.getPlugins()).thenReturn(cfyPluginList);
+        String actual = subject.getPluginCount(mockedRequest);
+        assertTrue(actual.contains("1"));
+    }
+    
+    @Test
+    public final void testDeleteBlueprint() throws Exception {
+        String json = "{\"202\": \"OK\"}";       
+             
+        doNothing().doThrow(httpException).doThrow(Exception.class).when(restClient).deleteBlueprint(Mockito.any(), Mockito.any());
+    
+        String actual = subject.deleteBlueprint("id", "tenant", mockedRequest, mockedResponse);
+        assertTrue(actual.equals(json));
+        
+        actual = subject.deleteBlueprint("id", "tenant", mockedRequest, mockedResponse);
+        assertTrue(actual.contains("error"));
+        
+        actual = subject.deleteBlueprint("id", "tenant", mockedRequest, mockedResponse);
+        assertTrue(actual.contains("error"));
+    }
+    
+    @Test
+    public final void testGetDeploymentsForType() throws Exception {              
+        String[] testTypeIds = {"44234234"};
+        ServiceRef expectedSrvc = new ServiceRef("dcae_dtiapi_1902", "432423", "433434");
+        Collection<ServiceRef> expectedSrvcIds = new ArrayList<ServiceRef>();
+        expectedSrvcIds.add(expectedSrvc);
+        ServiceRefList expectedSrvcRefList = new ServiceRefList(expectedSrvcIds, 1);
+
+        CloudifyDeployedTenant cfyDepTen = 
+            new CloudifyDeployedTenant("id", "tenant_name", "created_at", "updated_at");
+        
+        List<CloudifyDeployedTenant> cfyDeplTenList = new ArrayList<>();
+        cfyDeplTenList.add(cfyDepTen);
+        
+        when(restClient.getDeploymentForBlueprint(Mockito.any())).thenReturn(cfyDeplTenList);
+        
+        when(invClient.getServicesForType(Matchers.<ServiceQueryParams>any()))
+            .thenReturn(expectedSrvcRefList);
+        String actual = subject.getDeploymentsForType(mockedRequest, testTypeIds);
+        assertTrue(actual.contains(testTypeIds[0]));
+    }
+    
+    @Test
+    @Ignore
+    public final void testCacheOwnerDeployMap() {
+        
+    }
+    
+    @Test
+    public final void testGetExecutionsPerTenant() throws Exception {
+        String tenantsList =
+            "{\"items\": [{\"id\": 1, \"name\": \"default_tenant\", \"dName\": \"default_tenant\" }, "
+                + "{\"id\": 2, \"name\": \"dyh1b1902\", \"dName\": \"dyh1b1902\"}], "
+                + "\"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}";
+        CloudifyTenantList tenantData = null;
+        try {
+            tenantData = objectMapper.readValue(tenantsList, CloudifyTenantList.class);
+        } catch (Exception e) {
+        }
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        Mockito.when(restClient.getTenants()).thenReturn(tenantData);
+        
+        CloudifyExecution cldExecution =
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
+        
+        List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
+
+        cldExecutionList.add(cldExecution);
+
+        CloudifyExecutionList cloudifyExecutionList =
+            new CloudifyExecutionList(cldExecutionList, null);
+        
+        when(restClient.getExecutionsSummaryPerTenant(Mockito.any()))
+            .thenReturn(cloudifyExecutionList).thenReturn(cloudifyExecutionList)
+            .thenReturn(cloudifyExecutionList);
+        
+        String actual = subject.getExecutionsPerTenant(mockedRequest, "default_tenant", "failed");
+        assertFalse(actual.contains("execution_id1"));
+        actual = subject.getExecutionsPerTenant(mockedRequest, "default_tenant", "successful");
+        assertTrue(actual.contains("execution_id1"));
+        actual = subject.getExecutionsPerTenant(mockedRequest, null, "successful");
+        assertTrue(actual.contains("execution_id1"));
+    }
+    
+    @Test
+    public final void testGetExecutionsPerTenant_error() throws Exception {
+        String tenantsList =
+            "{\"items\": [{\"id\": 1, \"name\": \"default_tenant\", \"dName\": \"default_tenant\" }, "
+                + "{\"id\": 2, \"name\": \"dyh1b1902\", \"dName\": \"dyh1b1902\"}], "
+                + "\"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}";
+        CloudifyTenantList tenantData = null;
+        try {
+            tenantData = objectMapper.readValue(tenantsList, CloudifyTenantList.class);
+        } catch (Exception e) {
+        }
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        Mockito.when(restClient.getTenants()).thenReturn(tenantData);
+        
+        CloudifyExecution cldExecution =
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
+        
+        List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
+
+        cldExecutionList.add(cldExecution);
+
+        CloudifyExecutionList cloudifyExecutionList =
+            new CloudifyExecutionList(cldExecutionList, null);
+        
+        when(restClient.getExecutionsSummaryPerTenant(Mockito.any()))
+            .thenThrow(Exception.class).thenThrow(Exception.class).thenThrow(Exception.class);
+        
+        String actual = subject.getExecutionsPerTenant(mockedRequest, "default_tenant", "failed");
+        assertTrue(actual.contains("error"));
+        
+        actual = subject.getExecutionsPerTenant(mockedRequest, "default_tenant", "successful");
+        assertTrue(actual.contains("error"));
+        
+        actual = subject.getExecutionsPerTenant(mockedRequest, null, "failed");
+        assertTrue(actual.contains("error"));
+    }
+    
+    @Test
+    public final void testQueryExecution() throws Exception {      
+        CloudifyExecution cldExecution =
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);      
+        List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
+        cldExecutionList.add(cldExecution);
+        
+        when(restClient.getExecutionIdSummary(
+            Mockito.any(), Mockito.any())).thenReturn(cldExecution);
+        
+        String actual = subject.queryExecution("id", "tenant", mockedRequest);
+        assertTrue(actual.contains("items"));
+    }
+     
+    @SuppressWarnings("unchecked")
+    @Test
+    public final void testGetActiveExecutions() throws Exception {
+        String tenantsList =
+            "{\"items\": [{\"id\": 1, \"name\": \"default_tenant\", \"dName\": \"default_tenant\" }, "
+                + "{\"id\": 2, \"name\": \"dyh1b1902\", \"dName\": \"dyh1b1902\"}], "
+                + "\"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}";
+        CloudifyTenantList tenantData = null;
+        try {
+            tenantData = objectMapper.readValue(tenantsList, CloudifyTenantList.class);
+        } catch (Exception e) {
+        }
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        Mockito.when(restClient.getTenants()).thenReturn(tenantData).thenThrow(Exception.class);
+        
+        CloudifyExecution cldExecution =
+            new CloudifyExecution("started", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
+        
+        List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
+
+        cldExecutionList.add(cldExecution);
+
+        CloudifyExecutionList cloudifyExecutionList =
+            new CloudifyExecutionList(cldExecutionList, null);
+        
+        when(restClient.getExecutionsSummaryPerTenant(Mockito.any()))
+            .thenReturn(cloudifyExecutionList).thenReturn(cloudifyExecutionList);
+        
+        String actual = subject.getActiveExecutions(mockedRequest);
+        assertTrue(actual.contains("execution_id1"));
+        actual = subject.getActiveExecutions(mockedRequest);
+        assertTrue(actual.contains("error"));
+        
+    }
+    
+    @Test
+    public final void testGetNodeInstanceDetails() throws Exception {
+        
+        Map<String, Object> runtime_properties = 
+            new HashMap<>();
+        runtime_properties.put("key1", "value1");
+        
+        CloudifyNodeInstance cfyNodeInst = 
+            new CloudifyNodeInstance("node_instance_id1", runtime_properties);
+
+        List<CloudifyNodeInstance> cfyNodeInstItems = new ArrayList<CloudifyNodeInstance>();
+
+        cfyNodeInstItems.add(cfyNodeInst);
+
+        CloudifyNodeInstanceList cfyNodeInstList =
+            new CloudifyNodeInstanceList(cfyNodeInstItems, null);
+        
+        when(restClient.getNodeInstanceDetails(Mockito.any(), Mockito.any())).
+        thenReturn(cfyNodeInstList).thenThrow(httpException).
+        thenThrow(Exception.class);
+        
+        String actual = 
+            subject.getNodeInstanceDetails("deploymentId", "tenant", mockedRequest);
+        assertTrue(actual.contains("node_instance_id1"));
+        
+        actual = 
+            subject.getNodeInstanceDetails("deploymentId", "tenant", mockedRequest);
+        assertTrue(actual.contains("error"));
+        
+        actual = 
+            subject.getNodeInstanceDetails("deploymentId", "tenant", mockedRequest);
+        assertTrue(actual.contains("error"));  
+    }
+    
+    @Test
+    public final void testGetNodeInstances() throws Exception {
+        CloudifyNodeInstanceId cfyNodeInst = new CloudifyNodeInstanceId("node_instance_id1");
+
+        List<CloudifyNodeInstanceId> cfyNodeInstItems = new ArrayList<CloudifyNodeInstanceId>();
+
+        cfyNodeInstItems.add(cfyNodeInst);
+
+        CloudifyNodeInstanceIdList cfyNodeInstList =
+            new CloudifyNodeInstanceIdList(cfyNodeInstItems, null);
+        
+        when(restClient.getNodeInstances(Mockito.any(), Mockito.any())).
+        thenReturn(cfyNodeInstList).thenThrow(httpException).
+        thenThrow(Exception.class);
+        
+        String actual = 
+            subject.getNodeInstances("deploymentId", "tenant", mockedRequest);
+        assertTrue(actual.contains("node_instance_id1"));
+        
+        actual = 
+            subject.getNodeInstances("deploymentId", "tenant", mockedRequest);
+        assertTrue(actual.contains("error"));
+        
+        actual = 
+            subject.getNodeInstances("deploymentId", "tenant", mockedRequest);
+        assertTrue(actual.contains("error"));
+    }
+    
+    @Test
+    public final void testGetPlugins() throws Exception {
+        CloudifyPlugin sampleData = 
+            new CloudifyPlugin("plugin1", "202001", "linux", "linux_k8s_plugin", "20200801");
+
+        List<CloudifyPlugin> cfyPlugins = new ArrayList<CloudifyPlugin>();
+        cfyPlugins.add(sampleData);
+
+        CloudifyPluginList.Metadata.Pagination pageObj =
+            new CloudifyPluginList.Metadata.Pagination(1, 0, 1);
+        CloudifyPluginList.Metadata metadata = new CloudifyPluginList.Metadata(pageObj);
+
+        CloudifyPluginList cfyPluginList = new CloudifyPluginList(cfyPlugins, metadata);
+    
+        when(restClient.getPlugins()).thenReturn(cfyPluginList).thenThrow(Exception.class);
+        String actual = subject.getPlugins(mockedRequest);
+        assertTrue(actual.contains("plugin1"));
+        
+        actual = subject.getPlugins(mockedRequest);
+        assertTrue(actual.contains("error"));
+    }
+    
+    @Test
+    @Ignore
+    public final void testGetSecrets() {
+        
+    }
+    
+    @Test
+    @Ignore
+    public final void testGetSecret() {
+        
+    }
+    
+    @Test
+    @Ignore
+    public final void testDeleteSecret() {
+        
+    }
+    
+    @Test
+    @Ignore
+    public final void testCreateSecret() {
+    }
+    
     @SuppressWarnings({"unchecked", "unchecked"})
     @Test
     public final void testGetBlueprintById() throws Exception {
@@ -196,93 +619,13 @@ public class CloudifyControllerTest extends MockitoTestSuite {
         actualResult = subject.getDeploymentById("id1", null, mockedRequest);
         assertTrue(actualResult.contains("error"));
     }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testGetTenantStatusForService() throws Exception {
-
-        String[] deplIds = {"id1", "id2"};
-
-        CloudifyDeployedTenant cldDeplTenant = new CloudifyDeployedTenant("id1", "bp1", "tenant1");
-
-        List<CloudifyDeployedTenant> cldDeplTenantList = new ArrayList<CloudifyDeployedTenant>();
-
-        cldDeplTenantList.add(cldDeplTenant);
-
-        CloudifyDeployedTenantList cldDeployedTenantList =
-            new CloudifyDeployedTenantList(cldDeplTenantList, null);
-
-        CloudifyTenant cldTenant = new CloudifyTenant("tenant1", "tenant1", "tenant_id1");
-
-        List<CloudifyTenant> cldfyTenantList = new ArrayList<CloudifyTenant>();
-        cldfyTenantList.add(cldTenant);
-
-        CloudifyTenantList cloudifyTenantList = new CloudifyTenantList(cldfyTenantList, null);
-
-        CloudifyExecution cldExecution =
-            new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1",
-                "tenant1", "error", "execution_id1", null, false, false);
-
-        List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
-
-        cldExecutionList.add(cldExecution);
-
-        CloudifyExecutionList cloudifyExecutionList =
-            new CloudifyExecutionList(cldExecutionList, null);
-
-        Map<String, Object> plan = new HashMap<String, Object>();
-        HashMap<String, String> plugins_to_install = new HashMap<String, String>();
-        plugins_to_install.put("name", "helm-plugin");
-        ArrayList<HashMap<String, String>> deployment_plugins_to_install =
-            new ArrayList<HashMap<String, String>>();
-
-        deployment_plugins_to_install.add(plugins_to_install);
-        plan.put("deployment_plugins_to_install", deployment_plugins_to_install);
-
-        Map<String, String> workflows = new HashMap<String, String>();
-        workflows.put("status", "workflowshelm");
-        plan.put("workflows", workflows);
-
-        CloudifyBlueprint cldBp =
-            new CloudifyBlueprint("file1", "description1", "343242", "3423423", "id1", plan);
-
-        List<CloudifyBlueprint> items = new ArrayList<CloudifyBlueprint>();
-        items.add(cldBp);
-
-        CloudifyBlueprintList.Metadata.Pagination pageObj =
-            new CloudifyBlueprintList.Metadata.Pagination(1, 0, 1);
-
-        CloudifyBlueprintList.Metadata metadata = new CloudifyBlueprintList.Metadata(pageObj);
-
-        CloudifyBlueprintList cldBpList = new CloudifyBlueprintList(items, metadata);
-
-        when(restClient.getTenants()).thenReturn(cloudifyTenantList);
-
-        when(restClient.getTenantInfoFromDeploy(Mockito.any())).thenReturn(cldDeployedTenantList);
-
-        when(restClient.getExecutionsSummary(Mockito.any(), Mockito.any()))
-            .thenReturn(cloudifyExecutionList);
-
-        when(restClient.getBlueprint(Mockito.any(), Mockito.any())).thenReturn(cldBpList)
-            .thenThrow(Exception.class).thenThrow(httpException);
-
-        String actualResult = subject.getTenantStatusForService(mockedRequest, deplIds);
-        assertTrue(actualResult.contains("successful"));
-
-        actualResult = subject.getTenantStatusForService(mockedRequest, deplIds);
-        assertTrue(actualResult.contains("error"));
-
-        actualResult = subject.getTenantStatusForService(mockedRequest, deplIds);
-        assertTrue(actualResult.contains("error"));
-    }
-
-    @SuppressWarnings("unchecked")
+    
     @Test
     public void testGetExecutionsByPage() throws Exception {
         CloudifyExecution cldExecution =
-            new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1",
-                "tenant1", "error", "execution_id1", null, false, false);
-
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
+        
         List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
 
         cldExecutionList.add(cldExecution);
@@ -301,8 +644,8 @@ public class CloudifyControllerTest extends MockitoTestSuite {
         CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
 
         CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata);
-
-        when(restClient.getDeployments()).thenReturn(cldDeployList);
+               
+        when(restClient.getDeployments(Mockito.any(), Mockito.anyInt(), Mockito.anyInt())).thenReturn(cldDeployList);
         when(restClient.getExecutions(Mockito.any(), Mockito.any()))
             .thenReturn(cloudifyExecutionList).thenThrow(Exception.class)
             .thenReturn(cloudifyExecutionList);
@@ -317,13 +660,13 @@ public class CloudifyControllerTest extends MockitoTestSuite {
         actualResult = subject.getExecutionsByPage(mockedRequest, null, "successful", "tenant1");
         assertTrue(actualResult.contains("successful"));
     }
-
+/*
     @SuppressWarnings("unchecked")
     @Test
     public void testGetExecutionByIdAndDeploymentId() throws Exception {
         CloudifyExecution cldExecution =
-            new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1",
-                "tenant1", "error", "execution_id1", null, false, false);
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
 
         List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
 
@@ -347,7 +690,7 @@ public class CloudifyControllerTest extends MockitoTestSuite {
             "tenant", mockedRequest);
         assertTrue(actualResult.contains("error"));
     }
-
+*/
     @SuppressWarnings("unchecked")
     @Test
     public void testGetExecutionEventsById() throws Exception {
@@ -384,8 +727,9 @@ public class CloudifyControllerTest extends MockitoTestSuite {
     @SuppressWarnings("unchecked")
     @Test
     public void testStartExecution() throws Exception {
-        CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "install",
-            false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false);
+        CloudifyExecution cldExecution =
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
 
         Map<String, Object> params = new HashMap<String, Object>();
         params.put("key1", "value1");
@@ -401,12 +745,22 @@ public class CloudifyControllerTest extends MockitoTestSuite {
 
         CloudifyNodeInstanceIdList cfyNodeInstList =
             new CloudifyNodeInstanceIdList(cfyNodeInstItems, null);
-
+        
+        String secretTokenStr =
+            "{\"created_at\": \"created_ts\", \"key\": \"acl_key\", \"updated_at\": \"updated_ts\", \"value\": \"acl_token_val\", \"visibility\": \"global\", \"is_hidden_value\": \"false\", \"tenant_name\": \"tenant\", \"resource_availability\": \"rsrc\"}";          
+        CloudifySecret secretData = null;
+        try {
+            secretData = objectMapper.readValue(secretTokenStr, CloudifySecret.class);
+        } catch (Exception e) {
+            
+        }
+        when(restClient.getSecret(Mockito.any(), Mockito.any())).thenReturn(secretData);
+        
         when(restClient.getNodeInstanceId(Mockito.any(), Mockito.any()))
             .thenReturn(cfyNodeInstList);
 
         when(restClient.startExecution(Matchers.<CloudifyExecutionRequest>any()))
-            .thenReturn(cfyExecObj).thenThrow(Exception.class).thenThrow(httpException);
+            .thenReturn(cldExecution).thenThrow(Exception.class).thenThrow(httpException);
 
         String actualResult = subject.startExecution(mockedRequest, cfyExecReq);
         assertTrue(actualResult.contains("execution_id1"));
@@ -418,32 +772,6 @@ public class CloudifyControllerTest extends MockitoTestSuite {
         assertTrue(actualResult.contains("error"));
     }
 
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testUpdateDeployment() throws Exception {
-
-        CloudifyDeploymentUpdateRequest cfyDeployUpdateReq =
-            new CloudifyDeploymentUpdateRequest("deployment_id", "update", false, false,
-                "node_instance_id1", "4", "1000", "image", 2, "my_container");
-
-        CloudifyDeploymentUpdateResponse cfyDeployUpdateResp = new CloudifyDeploymentUpdateResponse(
-            "terminated", "created_at", "update", false, "blueprint_id", "deployment_id", "", "id1",
-            null, "tenant1", "junit", false, "resource_availability");
-
-        when(restClient.updateDeployment(Matchers.<CloudifyDeploymentUpdateRequest>any()))
-            .thenReturn(cfyDeployUpdateResp).thenThrow(Exception.class).thenThrow(httpException);
-
-        String actualResult = subject.updateDeployment(mockedRequest, cfyDeployUpdateReq);
-        assertTrue(actualResult.contains("terminated"));
-
-        actualResult = subject.updateDeployment(mockedRequest, cfyDeployUpdateReq);
-        assertTrue(actualResult.contains("error"));
-
-        actualResult = subject.updateDeployment(mockedRequest, cfyDeployUpdateReq);
-        assertTrue(actualResult.contains("error"));
-
-    }
-
     @SuppressWarnings("unchecked")
     @Test
     public void testGetNodeInstanceId() throws Exception {
@@ -506,8 +834,9 @@ public class CloudifyControllerTest extends MockitoTestSuite {
         HttpHeaders httpHeader = new HttpHeaders();
         httpHeader.put("tenant", tenants);
 
-        CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "cancel",
-            false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false);
+        CloudifyExecution cfyExecObj =
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
 
         when(restClient.cancelExecution(Mockito.any(), Mockito.any(), Mockito.any()))
             .thenReturn(cfyExecObj).thenThrow(Exception.class).thenThrow(httpException);
diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/CommonApiControllerTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/controller/CommonApiControllerTest.java
deleted file mode 100644 (file)
index 7097275..0000000
+++ /dev/null
@@ -1,791 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * 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.
- * ============LICENSE_END=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-
-package org.onap.ccsdk.dashboard.controller;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.when;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Stream;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Matchers;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.onap.ccsdk.dashboard.core.MockUser;
-import org.onap.ccsdk.dashboard.core.MockitoTestSuite;
-import org.onap.ccsdk.dashboard.domain.EcdComponent;
-import org.onap.ccsdk.dashboard.exceptions.BadRequestException;
-import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException;
-import org.onap.ccsdk.dashboard.exceptions.DownstreamException;
-import org.onap.ccsdk.dashboard.exceptions.ServerErrorException;
-import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException;
-import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException;
-import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenant;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployment;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecution;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstance;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceId;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceList;
-import org.onap.ccsdk.dashboard.model.CloudifyTenant;
-import org.onap.ccsdk.dashboard.model.CloudifyTenantList;
-import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentInput;
-import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest;
-import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse;
-import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponseLinks;
-import org.onap.ccsdk.dashboard.model.inventory.Service;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceList;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceRef;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceRefList;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceType;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeList;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest;
-import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeUploadRequest;
-import org.onap.ccsdk.dashboard.rest.CloudifyClient;
-import org.onap.ccsdk.dashboard.rest.DeploymentHandlerClient;
-import org.onap.ccsdk.dashboard.rest.InventoryClient;
-import org.onap.ccsdk.dashboard.service.ControllerEndpointService;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.client.HttpServerErrorException;
-import org.springframework.web.client.HttpStatusCodeException;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
-
-public class CommonApiControllerTest extends MockitoTestSuite {
-
-    @Mock
-    private CloudifyClient cfyClient;
-
-    @Mock
-    private InventoryClient inventoryClient;
-
-    @Mock
-    DeploymentHandlerClient deploymentHandlerClient;
-
-    @Mock
-    ControllerEndpointService controllerEndpointService;
-
-    @InjectMocks
-    CommonApiController subject = new CommonApiController();
-
-    private HttpStatusCodeException httpException =
-        new HttpServerErrorException(HttpStatus.BAD_GATEWAY);
-
-    protected final ObjectMapper objectMapper = new ObjectMapper();
-
-    HttpServletRequest mockedRequest;
-    HttpServletResponse mockedResponse;
-
-    MockUser mockUser = new MockUser();
-    ServiceList deplList = null;
-    Service deplItem = null;
-
-    ServiceType bpItem = null;
-    ServiceType bpItem2 = null;
-    ServiceTypeList bpList = null;
-    ServiceTypeList bpList2 = null;
-
-    ServiceTypeRequest bpUploadItem = null;
-
-    BadRequestException badReqError;
-    ServiceAlreadyExistsException srvcExistError;
-    ServerErrorException serverError;
-    DownstreamException downStrmError;
-    JsonProcessingException jsonError;
-    DeploymentNotFoundException notFoundError;
-    private ServiceTypeNotFoundException serviceTypeException =
-        new ServiceTypeNotFoundException("Invalid blueprint");
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        objectMapper.registerModule(new Jdk8Module());
-        getExpectedDeployments();
-        getExpectedBueprints();
-        createBpUploadItem();
-        mockedRequest = getMockedRequest();
-        mockedResponse = getMockedResponse();
-        badReqError = new BadRequestException("bad request");
-        srvcExistError = new ServiceAlreadyExistsException("service already exists");
-        serverError = new ServerErrorException("Error occured in server");
-        downStrmError = new DownstreamException("error occured in downstream");
-        notFoundError = new DeploymentNotFoundException("item not found");
-    }
-
-    public void getExpectedDeployments()
-        throws JsonParseException, JsonMappingException, IOException {
-
-        deplItem = new Service("dcae_dtiapi_1902", null, "1552335532348", "1552335532348", null,
-            "dummyVnfId", null, "dummyVnfType", "dummyLocation", "dcae_dtiapi_1902", null);
-        Collection<Service> items = new ArrayList<Service>();
-        items.add(deplItem);
-
-        String pageLinks =
-            "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}";
-        ServiceList.PaginationLinks paginationLinks =
-            objectMapper.readValue(pageLinks, ServiceList.PaginationLinks.class);
-        int totalCount = 1;
-        deplList = new ServiceList(items, totalCount, paginationLinks);
-
-    }
-
-    public void getExpectedBueprints()
-        throws JsonParseException, JsonMappingException, IOException {
-        bpItem = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906,
-            "tosca_definitions_version: cloudify_dsl_1_3", "", "app1", "comp1").build();
-
-        Collection<ServiceType> items = new ArrayList<ServiceType>();
-        items.add(bpItem);
-
-        String pageLinks2 =
-            "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}";
-        ServiceTypeList.PaginationLinks paginationLinks =
-            objectMapper.readValue(pageLinks2, ServiceTypeList.PaginationLinks.class);
-        int totalCount = 1;
-        bpList = new ServiceTypeList(items, totalCount, paginationLinks);
-
-        bpItem2 = new ServiceType("xyz1731", "xyz1731-helm-1907", 1906,
-            "tosca_definitions_version: cloudify_dsl_1_3\\r\\nimports:\\r\\n  - http://www.getcloudify.org/spec/cloudify/4.2/types.yaml\\r\\n",
-            "app1", "comp1", null, null, null, null, null, null, "typeId", null, "created", null,
-            true);
-
-        Collection<ServiceType> items2 = new ArrayList<ServiceType>();
-        items2.add(bpItem2);
-
-        bpList2 = new ServiceTypeList(items2, totalCount, paginationLinks);
-    }
-
-    public void createBpUploadItem() {
-        bpUploadItem = ServiceTypeRequest.from(bpItem);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-    }
-
-    @Test
-    public final void testInsertComponent() throws Exception {
-        EcdComponent component1 = new EcdComponent();
-
-        component1.setCname("comp1");
-        component1.setCompId(100L);
-        component1.setDname("COMP1");
-
-        doNothing().when(controllerEndpointService).insertComponent(component1);
-
-        String actualResult = subject.insertComponent(mockedRequest, component1);
-        assertTrue(actualResult.contains("Inserted"));
-    }
-
-    @Test
-    public final void testGetComponents() throws Exception {
-        EcdComponent component1 = new EcdComponent();
-        EcdComponent component2 = new EcdComponent();
-
-        component1.setCname("comp1");
-        component1.setCompId(100L);
-        component1.setDname("COMP1");
-
-        component2.setCname("comp2");
-        component2.setCompId(200L);
-        component2.setDname("COMP2");
-
-        List<EcdComponent> compsList = new ArrayList<EcdComponent>();
-        compsList.add(component1);
-        compsList.add(component2);
-
-        when(controllerEndpointService.getComponents()).thenReturn(compsList);
-
-        String actualResult = subject.getComponents(mockedRequest);
-        assertTrue(actualResult.contains("comp1"));
-    }
-
-    @Test
-    public final void testGetTenants() throws Exception {
-        String tenantsList =
-            "{\"items\": [{\"id\": 1, \"name\": \"default_tenant\", \"dName\": \"default_tenant\" }, "
-                + "{\"id\": 2, \"name\": \"dyh1b1902\", \"dName\": \"dyh1b1902\"}], "
-                + "\"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}";
-        CloudifyTenantList sampleData = null;
-        try {
-            sampleData = objectMapper.readValue(tenantsList, CloudifyTenantList.class);
-        } catch (Exception e) {
-        }
-        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
-
-        Mockito.when(cfyClient.getTenants()).thenReturn(sampleData);
-
-        String tenantStr = subject.getTenants(mockedRequest);
-        assertTrue(tenantStr.contains("dyh1b"));
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testGetTenantStatusForService() throws Exception {
-        String[] deplIds = {"id1", "id2"};
-
-        CloudifyDeployedTenant cldDeplTenant = new CloudifyDeployedTenant("id1", "bp1", "tenant1");
-
-        List<CloudifyDeployedTenant> cldDeplTenantList = new ArrayList<CloudifyDeployedTenant>();
-
-        cldDeplTenantList.add(cldDeplTenant);
-
-        CloudifyDeployedTenantList cldDeployedTenantList =
-            new CloudifyDeployedTenantList(cldDeplTenantList, null);
-
-        CloudifyTenant cldTenant = new CloudifyTenant("tenant1", "tenant1", "tenant_id1");
-
-        List<CloudifyTenant> cldfyTenantList = new ArrayList<CloudifyTenant>();
-        cldfyTenantList.add(cldTenant);
-
-        CloudifyTenantList cloudifyTenantList = new CloudifyTenantList(cldfyTenantList, null);
-
-        CloudifyExecution cldExecution =
-            new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1",
-                "tenant1", "error", "execution_id1", null, false, false);
-
-        List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
-
-        cldExecutionList.add(cldExecution);
-
-        CloudifyExecutionList cloudifyExecutionList =
-            new CloudifyExecutionList(cldExecutionList, null);
-
-        when(cfyClient.getTenants()).thenReturn(cloudifyTenantList);
-
-        when(cfyClient.getTenantInfoFromDeploy(Mockito.any())).thenReturn(cldDeployedTenantList);
-
-        when(cfyClient.getExecutionsSummary(Mockito.any(), Mockito.any()))
-            .thenReturn(cloudifyExecutionList).thenThrow(Exception.class).thenThrow(httpException);
-
-        String actualResult = subject.getTenantStatusForService(mockedRequest, deplIds);
-        assertTrue(actualResult.contains("successful"));
-
-        actualResult = subject.getTenantStatusForService(mockedRequest, deplIds);
-        assertTrue(actualResult.contains("error"));
-
-        actualResult = subject.getTenantStatusForService(mockedRequest, deplIds);
-        assertTrue(actualResult.contains("error"));
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testCreateBlueprint() throws Exception {
-        ServiceTypeUploadRequest bpUploadReq = ServiceTypeUploadRequest.from(bpItem);
-
-        when(inventoryClient.addServiceType(Matchers.<ServiceTypeRequest>any()))
-            .thenThrow(BlueprintParseException.class).thenThrow(httpException)
-            .thenThrow(Exception.class).thenReturn(bpItem);
-
-        String actual1 = subject.createBlueprint(mockedRequest, bpUploadReq);
-        assertTrue(actual1.contains("error"));
-
-        String actual2 = subject.createBlueprint(mockedRequest, bpUploadReq);
-        assertTrue(actual2.contains("error"));
-
-        String actual3 = subject.createBlueprint(mockedRequest, bpUploadReq);
-        assertTrue(actual3.contains("error"));
-
-        String actual = subject.createBlueprint(mockedRequest, bpUploadReq);
-        assertTrue(actual.contains("app1"));
-
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testGetBlueprintsByPage() {
-        MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest();
-        mockedRequest1.addParameter("_include", "typeName,typeId,typeVersion");
-        mockedRequest1.addParameter("name", "xyz");
-
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> sampleStream1 = items.stream();
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
-            .thenReturn(sampleStream1).thenThrow(Exception.class).thenThrow(httpException);
-
-        String result = subject.getBlueprintsByPage(mockedRequest1);
-        assertTrue(result.contains("xyz"));
-
-        result = subject.getBlueprintsByPage(mockedRequest1);
-        assertTrue(result.contains("error"));
-
-        result = subject.getBlueprintsByPage(mockedRequest1);
-        assertTrue(result.contains("error"));
-
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testQueryBlueprintFilter() {
-        MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest();
-        mockedRequest1.addParameter("_include", "typeName,typeId,typeVersion");
-        mockedRequest1.addParameter("name", "xyz");
-
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> sampleStream1 = items.stream();
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
-            .thenReturn(sampleStream1).thenThrow(Exception.class).thenThrow(httpException);
-
-        String result = subject.queryBlueprintFilter(mockedRequest1);
-        assertTrue(result.contains("xyz"));
-
-        result = subject.queryBlueprintFilter(mockedRequest1);
-        assertTrue(result.contains("error"));
-
-        result = subject.queryBlueprintFilter(mockedRequest1);
-        assertTrue(result.contains("error"));
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testGetDeploymentsByPage() {
-        CloudifyDeployedTenant cldDeplTenant =
-            new CloudifyDeployedTenant("dcae_dtiapi_1902", "dcae_dtiapi_1902", "tenant1");
-
-        List<CloudifyDeployedTenant> cldDeplTenantList = new ArrayList<CloudifyDeployedTenant>();
-
-        cldDeplTenantList.add(cldDeplTenant);
-
-        CloudifyDeployedTenantList cldDeployedTenantList =
-            new CloudifyDeployedTenantList(cldDeplTenantList, null);
-
-        CloudifyTenant cldTenant = new CloudifyTenant("tenant1", "tenant1", "tenant_id1");
-
-        List<CloudifyTenant> cldfyTenantList = new ArrayList<CloudifyTenant>();
-        cldfyTenantList.add(cldTenant);
-
-        CloudifyTenantList cloudifyTenantList = new CloudifyTenantList(cldfyTenantList, null);
-
-        MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest();
-        mockedRequest1.addParameter("_include", "id");
-        mockedRequest1.addParameter("searchBy", "dti");
-
-        Collection<Service> items = deplList.items;
-
-        when(cfyClient.getTenants()).thenReturn(cloudifyTenantList);
-
-        when(cfyClient.getTenantInfoFromDeploy(Mockito.any())).thenReturn(cldDeployedTenantList)
-            .thenThrow(Exception.class).thenThrow(httpException).thenReturn(cldDeployedTenantList)
-            .thenReturn(cldDeployedTenantList);
-
-        Stream<Service> sampleStream1 = items.stream();
-        Stream<Service> sampleStream2 = items.stream();
-        Stream<Service> sampleStream3 = items.stream();
-
-        Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1)
-            .thenReturn(sampleStream2).thenReturn(sampleStream3).thenThrow(Exception.class)
-            .thenThrow(httpException);
-
-        String result = subject.getDeploymentsByPage("dcae_dtiapi_1902", mockedRequest1);
-        assertTrue(result.contains("dti"));
-
-        result = subject.getDeploymentsByPage("dcae_dtiapi_1902", mockedRequest1);
-        assertTrue(result.contains("dti"));
-
-        result = subject.getDeploymentsByPage("dcae_dtiapi_1902", mockedRequest1);
-        assertTrue(result.contains("dti"));
-
-        result = subject.getDeploymentsByPage("dcae_dtiapi_1902", mockedRequest1);
-        assertTrue(result.contains("error"));
-
-        result = subject.getDeploymentsByPage("dcae_dtiapi_1902", mockedRequest1);
-        assertTrue(result.contains("error"));
-
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testGetAllDeploymentsByPage() {
-        CloudifyDeployedTenant cldDeplTenant =
-            new CloudifyDeployedTenant("dcae_dtiapi_1902", "dcae_dtiapi_1902", "tenant1");
-
-        List<CloudifyDeployedTenant> cldDeplTenantList = new ArrayList<CloudifyDeployedTenant>();
-
-        cldDeplTenantList.add(cldDeplTenant);
-
-        CloudifyDeployedTenantList cldDeployedTenantList =
-            new CloudifyDeployedTenantList(cldDeplTenantList, null);
-
-        CloudifyTenant cldTenant = new CloudifyTenant("tenant1", "tenant1", "tenant_id1");
-
-        List<CloudifyTenant> cldfyTenantList = new ArrayList<CloudifyTenant>();
-        cldfyTenantList.add(cldTenant);
-
-        CloudifyTenantList cloudifyTenantList = new CloudifyTenantList(cldfyTenantList, null);
-
-        MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest();
-        mockedRequest1.addParameter("_include", "id");
-        mockedRequest1.addParameter("searchBy", "dti");
-
-        Collection<Service> items = deplList.items;
-
-        when(cfyClient.getTenants()).thenReturn(cloudifyTenantList);
-
-        when(cfyClient.getTenantInfoFromDeploy(Mockito.any())).thenReturn(cldDeployedTenantList)
-            .thenThrow(Exception.class).thenThrow(httpException).thenReturn(cldDeployedTenantList)
-            .thenReturn(cldDeployedTenantList);
-
-        Stream<Service> sampleStream1 = items.stream();
-        Stream<Service> sampleStream2 = items.stream();
-        Stream<Service> sampleStream3 = items.stream();
-
-        Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1)
-            .thenReturn(sampleStream2).thenReturn(sampleStream3).thenThrow(Exception.class)
-            .thenThrow(httpException);
-
-        String result = subject.getAllDeploymentsByPage(mockedRequest1);
-        assertTrue(result.contains("dti"));
-
-        result = subject.getAllDeploymentsByPage(mockedRequest1);
-        assertTrue(result.contains("dti"));
-
-        result = subject.getAllDeploymentsByPage(mockedRequest1);
-        assertTrue(result.contains("dti"));
-
-        result = subject.getAllDeploymentsByPage(mockedRequest1);
-        assertTrue(result.contains("error"));
-
-        result = subject.getAllDeploymentsByPage(mockedRequest1);
-        assertTrue(result.contains("error"));
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testGetDeploymentRevisions() throws Exception {
-        CloudifyNodeInstance cfyNodeInstance = new CloudifyNodeInstance("id1", null);
-
-        List<CloudifyNodeInstance> cfyNodeInstanceItems = new ArrayList<CloudifyNodeInstance>();
-        cfyNodeInstanceItems.add(cfyNodeInstance);
-
-        CloudifyNodeInstanceList cfyNodeInstList =
-            new CloudifyNodeInstanceList(cfyNodeInstanceItems, null);
-
-        when(cfyClient.getNodeInstanceVersion(Mockito.any(), Mockito.any()))
-            .thenReturn(cfyNodeInstList).thenThrow(Exception.class).thenThrow(httpException);
-
-        String actualResult =
-            subject.getDeploymentRevisions("deploymentId", "tenant", mockedRequest);
-        assertTrue(actualResult.contains("id1"));
-
-        actualResult = subject.getDeploymentRevisions("deploymentId", "tenant", mockedRequest);
-        assertTrue(actualResult.contains("error"));
-
-        actualResult = subject.getDeploymentRevisions("deploymentId", "tenant", mockedRequest);
-        assertTrue(actualResult.contains("error"));
-    }
-
-    @Test
-    public final void testGetDeploymentInputs() throws Exception {
-
-        Map<String, Object> inputHash = new HashMap<String, Object>();
-        inputHash.put("key1", "value1");
-
-        CloudifyDeployment cldDeployment =
-            new CloudifyDeployment("description", "blueprint_id", "created_at", "updated_at", "id",
-                inputHash, null, null, null, null, null, null, "tenant");
-
-        List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>();
-        cfyDeployItems.add(cldDeployment);
-
-        CloudifyDeploymentList.Metadata.Pagination pageObj =
-            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
-        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
-
-        CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata);
-
-        when(cfyClient.getDeploymentInputs(Matchers.any(), Matchers.any()))
-            .thenReturn(cldDeployList);
-
-        String actualResult = subject.getDeploymentInputs("deploymentId", "tenant", mockedRequest);
-        assertTrue(actualResult.contains("blueprint_id"));
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testModifyDeployment() throws Exception {
-        CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "install",
-            false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false);
-
-        Map<String, Object> params = new HashMap<String, Object>();
-        params.put("tenant", "tenant1");
-        params.put("workflow", "upgrade");
-
-        CloudifyExecutionRequest cfyExecReq = new CloudifyExecutionRequest("deployment_id",
-            "upgrade", false, false, "tenant1", params);
-
-        CloudifyNodeInstanceId cfyNodeInst = new CloudifyNodeInstanceId("node_instance_id1");
-
-        List<CloudifyNodeInstanceId> cfyNodeInstItems = new ArrayList<CloudifyNodeInstanceId>();
-
-        cfyNodeInstItems.add(cfyNodeInst);
-
-        CloudifyNodeInstanceIdList cfyNodeInstList =
-            new CloudifyNodeInstanceIdList(cfyNodeInstItems, null);
-
-        when(cfyClient.getNodeInstanceId(Mockito.any(), Mockito.any())).thenReturn(cfyNodeInstList);
-
-        when(cfyClient.startExecution(Matchers.<CloudifyExecutionRequest>any()))
-            .thenReturn(cfyExecObj).thenThrow(Exception.class).thenThrow(httpException);
-
-        String inputParamStr = "{\"tenant\": \"tenant1\", \"workflow\":\"upgrade\"}";
-
-        InputStream is = new ByteArrayInputStream(inputParamStr.getBytes());
-
-        String actualResult = subject.modifyDeployment("depId", mockedRequest, is);
-        assertTrue(actualResult.contains("execution_id1"));
-
-        actualResult = subject.modifyDeployment("depId", mockedRequest, is);
-        assertTrue(actualResult.contains("error"));
-
-        actualResult = subject.modifyDeployment("depId", mockedRequest, is);
-        assertTrue(actualResult.contains("error"));
-
-    }
-
-    @Test
-    public final void testGetServicesForType() throws Exception {
-        ServiceRef expectedSrvc = new ServiceRef("dcae_dtiapi_1902", "432423", "433434");
-        Collection<ServiceRef> expectedSrvcIds = new ArrayList<ServiceRef>();
-        expectedSrvcIds.add(expectedSrvc);
-        ServiceRefList expectedSrvcRefList = new ServiceRefList(expectedSrvcIds, 1);
-
-        when(inventoryClient.getServicesForType(Matchers.<ServiceQueryParams>any()))
-            .thenReturn(expectedSrvcRefList);
-        String actual = subject.getServicesForType(mockedRequest, "typeId1");
-        assertTrue(actual.contains("typeId1"));
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testCreateDeployment() throws Exception {
-        DeploymentInput deployInput1 = new DeploymentInput("component1", "tag1",
-            "xyz1731-helm-1906", 1906, "blueprintId", null, "tenant1");
-
-        DeploymentInput deployInput2 = new DeploymentInput("component1", "tag1",
-            "xyz1731-helm-1906", 1906, null, null, "tenant1");
-
-        DeploymentResponseLinks expectLink = new DeploymentResponseLinks("self", "status");
-        DeploymentResponse expectResp = new DeploymentResponse("req1", expectLink);
-
-        Collection<ServiceType> items = bpList2.items;
-        Stream<ServiceType> sampleStream1 = items.stream();
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
-            .thenReturn(sampleStream1);
-
-        String actualResp0 = subject.createDeployment(mockedRequest, deployInput2);
-        assertTrue(actualResp0.contains("error"));
-
-        StringBuffer expectedStrBuff = new StringBuffer();
-        expectedStrBuff.append("http://oom.s2.com");
-        when(mockedRequest.getRequestURL()).thenReturn(expectedStrBuff);
-
-        when(deploymentHandlerClient.putDeployment(Matchers.anyString(), Matchers.anyString(),
-            Matchers.<DeploymentRequest>any())).thenReturn(expectResp).thenThrow(badReqError)
-                .thenThrow(srvcExistError).thenThrow(serverError).thenThrow(downStrmError)
-                .thenThrow(Exception.class);
-
-        String actualResp = subject.createDeployment(mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("component1"));
-
-        actualResp = subject.createDeployment(mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.createDeployment(mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.createDeployment(mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.createDeployment(mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.createDeployment(mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("error"));
-
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testUpdateDeployment() throws Exception {
-
-        DeploymentInput deployInput1 = new DeploymentInput("component1", "tag1",
-            "xyz1731-helm-1906", 1906, "blueprintId", null, "tenant1");
-
-        DeploymentResponseLinks expectLink = new DeploymentResponseLinks("self", "status");
-        DeploymentResponse expectResp = new DeploymentResponse("req1", expectLink);
-
-        Collection<ServiceType> items = bpList2.items;
-        Stream<ServiceType> sampleStream1 = items.stream();
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
-            .thenReturn(sampleStream1);
-
-        when(deploymentHandlerClient.updateDeployment(Matchers.anyString(), Matchers.anyString(),
-            Matchers.<DeploymentRequest>any())).thenReturn(expectResp).thenThrow(badReqError)
-                .thenThrow(srvcExistError).thenThrow(serverError).thenThrow(downStrmError)
-                .thenThrow(Exception.class);
-
-        String actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("req1"));
-
-        actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.updateDeployment("id1", mockedRequest, deployInput1);
-        assertTrue(actualResp.contains("error"));
-    }
-
-    @Test
-    public final void testGetExecutionByDeploymentId() throws Exception {
-
-        CloudifyExecution cldExecution =
-            new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1",
-                "tenant1", "error", "execution_id1", null, false, false);
-
-        List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
-
-        cldExecutionList.add(cldExecution);
-
-        CloudifyExecutionList cloudifyExecutionList =
-            new CloudifyExecutionList(cldExecutionList, null);
-
-        when(cfyClient.getExecutionsSummary(Mockito.any(), Mockito.any()))
-            .thenReturn(cloudifyExecutionList);
-
-        String actualResult =
-            subject.getExecutionByDeploymentId("dep_id", "tenant1", mockedRequest);
-        assertTrue(actualResult.contains("execution_id1"));
-    }
-
-    @Test
-    public final void testDeleteBlueprint() throws Exception {
-        String expected = "{\"202\": \"OK\"}";
-        doNothing().doThrow(serviceTypeException).doThrow(Exception.class).when(inventoryClient)
-            .deleteServiceType(Matchers.anyString());
-
-        String actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse);
-        assertEquals(expected, actual);
-
-        actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse);
-        assertTrue(actual.contains("error"));
-
-        actual = subject.deleteBlueprint("srvcId", mockedRequest, mockedResponse);
-        assertTrue(actual.contains("error"));
-    }
-
-    @Test
-    public final void testDeleteDeployment() throws Exception {
-        doNothing().doThrow(badReqError).doThrow(serverError).doThrow(downStrmError)
-            .doThrow(notFoundError).doThrow(Exception.class).when(deploymentHandlerClient)
-            .deleteDeployment(Matchers.anyString(), Matchers.anyString());
-
-        StringBuffer expectedStrBuff = new StringBuffer();
-        expectedStrBuff.append("http://oom.s2.com");
-        when(mockedRequest.getRequestURL()).thenReturn(expectedStrBuff);
-
-        String actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse);
-        assertFalse(actual.contains("error"));
-
-        actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse);
-        assertTrue(actual.contains("error"));
-
-        actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse);
-        assertTrue(actual.contains("error"));
-
-        actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse);
-        assertTrue(actual.contains("error"));
-
-        actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse);
-        assertTrue(actual.contains("error"));
-
-        actual = subject.deleteDeployment("dep1", mockedRequest, "tenant1", mockedResponse);
-        assertTrue(actual.contains("error"));
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testCancelExecution() throws Exception {
-        List<String> tenants = new ArrayList<String>();
-        tenants.add("tenant1");
-
-        HttpHeaders httpHeader = new HttpHeaders();
-        httpHeader.put("tenant", tenants);
-
-        CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "cancel",
-            false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false);
-
-        when(cfyClient.cancelExecution(Mockito.any(), Mockito.any(), Mockito.any()))
-            .thenReturn(cfyExecObj).thenThrow(Exception.class).thenThrow(httpException);
-
-        String actualResult =
-            subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse);
-        assertTrue(actualResult.contains("execution_id1"));
-
-        actualResult =
-            subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse);
-        assertTrue(actualResult.contains("error"));
-
-        actualResult =
-            subject.cancelExecution(httpHeader, "id1", null, mockedRequest, mockedResponse);
-        assertTrue(actualResult.contains("error"));
-    }
-
-}
index 3d71a2e..53657ed 100644 (file)
@@ -28,6 +28,8 @@ import static org.mockito.Mockito.when;
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -37,14 +39,15 @@ import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.onap.ccsdk.dashboard.controller.ConsulController.ConsulDataItem;
 import org.onap.ccsdk.dashboard.core.MockUser;
 import org.onap.ccsdk.dashboard.core.MockitoTestSuite;
-import org.onap.ccsdk.dashboard.model.ConsulDatacenter;
-import org.onap.ccsdk.dashboard.model.ConsulHealthServiceRegistration;
-import org.onap.ccsdk.dashboard.model.ConsulNodeInfo;
-import org.onap.ccsdk.dashboard.model.ConsulServiceHealth;
-import org.onap.ccsdk.dashboard.model.ConsulServiceInfo;
 import org.onap.ccsdk.dashboard.model.RestResponseSuccess;
+import org.onap.ccsdk.dashboard.model.consul.ConsulDatacenter;
+import org.onap.ccsdk.dashboard.model.consul.ConsulHealthServiceRegistration;
+import org.onap.ccsdk.dashboard.model.consul.ConsulNodeInfo;
+import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth;
+import org.onap.ccsdk.dashboard.model.consul.ConsulServiceInfo;
 import org.onap.ccsdk.dashboard.rest.ConsulClient;
 import org.onap.portalsdk.core.domain.User;
 import org.onap.portalsdk.core.web.support.UserUtils;
@@ -67,6 +70,8 @@ public class ConsulControllerTest extends MockitoTestSuite {
     MockUser mockUser = new MockUser();
     HttpClientErrorException httpException;
 
+    String[] svcTags = {"cfytenantname=onap"}; 
+    
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -87,7 +92,7 @@ public class ConsulControllerTest extends MockitoTestSuite {
             "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing",
             "This is a pgaas1_Service_ID health check",
             "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n",
-            "pgaas1_Service_ID", "pgaasServer1", 190199, 199395);
+            "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395);
 
         List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>();
         expectedCnslSrvcHlth.add(consulSrvcHlth);
@@ -118,7 +123,7 @@ public class ConsulControllerTest extends MockitoTestSuite {
             "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing",
             "This is a pgaas1_Service_ID health check",
             "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n",
-            "pgaas1_Service_ID", "pgaasServer1", 190199, 199395);
+            "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395);
 
         List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>();
         expectedCnslSrvcHlth.add(consulSrvcHlth);
@@ -160,7 +165,7 @@ public class ConsulControllerTest extends MockitoTestSuite {
             "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing",
             "This is a pgaas1_Service_ID health check",
             "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n",
-            "pgaas1_Service_ID", "pgaasServer1", 190199, 199395);
+            "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395);
 
         List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>();
         expectedCnslSrvcHlth.add(consulSrvcHlth);
@@ -193,123 +198,15 @@ public class ConsulControllerTest extends MockitoTestSuite {
         assertTrue(actualResult.contains("dc1"));
     }
 
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testRegisterService() throws Exception {
-        ConsulHealthServiceRegistration.EndpointCheck endPoint =
-            new ConsulHealthServiceRegistration.EndpointCheck("endpoint1", "interval1",
-                "description1", "name1");
-        List<ConsulHealthServiceRegistration.EndpointCheck> endPointList =
-            new ArrayList<ConsulHealthServiceRegistration.EndpointCheck>();
-        endPointList.add(endPoint);
-
-        List<String> tagList = new ArrayList<String>();
-        tagList.add("tag1");
-        tagList.add("tag2");
-
-        ConsulHealthServiceRegistration.ConsulServiceRegistration servcReg =
-            new ConsulHealthServiceRegistration.ConsulServiceRegistration("id1", "name1",
-                "address1", "port1", tagList, endPointList);
-        List<ConsulHealthServiceRegistration.ConsulServiceRegistration> servcRegList =
-            new ArrayList<ConsulHealthServiceRegistration.ConsulServiceRegistration>();
-        servcRegList.add(servcReg);
-
-        ConsulHealthServiceRegistration chsrObj = new ConsulHealthServiceRegistration(servcRegList);
-
-        RestResponseSuccess expectedResp = new RestResponseSuccess("Registration yielded code 0");
-        String expectedResult = objectMapper.writeValueAsString(expectedResp);
-
-        String expectedStr = "Registration yielded code 0";
-        when(consulClient.registerService(Matchers.<ConsulHealthServiceRegistration>any()))
-            .thenReturn(expectedStr).thenThrow(Exception.class).thenThrow(httpException);
-
-        String actualResult = subject.registerService(mockedRequest, chsrObj);
-        assertTrue(actualResult.equals(expectedResult));
-
-        actualResult = subject.registerService(mockedRequest, chsrObj);
-        assertTrue(actualResult.contains("error"));
-
-        actualResult = subject.registerService(mockedRequest, chsrObj);
-        assertTrue(actualResult.contains("error"));
-    }
-
-    @Test
-    public final void testRegisterService_SrvcError() throws Exception {
-        ConsulHealthServiceRegistration chsrObj = new ConsulHealthServiceRegistration(null);
-
-        String actualResult = subject.registerService(mockedRequest, chsrObj);
-        assertTrue(actualResult.contains("error"));
-    }
-
-    @Test
-    @Ignore
-    public final void testRegisterService_invalidSrvcError() throws Exception {
-        ConsulHealthServiceRegistration.EndpointCheck endPoint =
-            new ConsulHealthServiceRegistration.EndpointCheck("endpoint1", "interval1",
-                "description1", "name1");
-        List<ConsulHealthServiceRegistration.EndpointCheck> endPointList =
-            new ArrayList<ConsulHealthServiceRegistration.EndpointCheck>();
-        endPointList.add(endPoint);
-
-        List<String> tagList = new ArrayList<String>();
-        tagList.add("tag1");
-        tagList.add("tag2");
-
-        ConsulHealthServiceRegistration.ConsulServiceRegistration servcReg =
-            new ConsulHealthServiceRegistration.ConsulServiceRegistration("id1", "name2",
-                "address2", "port1", tagList, endPointList);
-        List<ConsulHealthServiceRegistration.ConsulServiceRegistration> servcRegList =
-            new ArrayList<ConsulHealthServiceRegistration.ConsulServiceRegistration>();
-        servcRegList.add(servcReg);
-
-        ConsulHealthServiceRegistration chsrObj = new ConsulHealthServiceRegistration(servcRegList);
-
-        String actualResult = subject.registerService(mockedRequest, chsrObj);
-        assertTrue(actualResult.contains("error"));
-    }
-
-    @Test
-    public final void testRegisterService_invalidEndptError() throws Exception {
-        ConsulHealthServiceRegistration.EndpointCheck endPoint =
-            new ConsulHealthServiceRegistration.EndpointCheck("", "", "description1", "name1");
-        List<ConsulHealthServiceRegistration.EndpointCheck> endPointList =
-            new ArrayList<ConsulHealthServiceRegistration.EndpointCheck>();
-        endPointList.add(endPoint);
-
-        List<String> tagList = new ArrayList<String>();
-        tagList.add("tag1");
-        tagList.add("tag2");
-
-        ConsulHealthServiceRegistration.ConsulServiceRegistration servcReg =
-            new ConsulHealthServiceRegistration.ConsulServiceRegistration("id1", "", "", "port1",
-                tagList, endPointList);
-        List<ConsulHealthServiceRegistration.ConsulServiceRegistration> servcRegList =
-            new ArrayList<ConsulHealthServiceRegistration.ConsulServiceRegistration>();
-        servcRegList.add(servcReg);
-
-        ConsulHealthServiceRegistration chsrObj = new ConsulHealthServiceRegistration(servcRegList);
-
-        String actualResult = subject.registerService(mockedRequest, chsrObj);
-        assertTrue(actualResult.contains("error"));
-    }
-
-    @SuppressWarnings("unchecked")
     @Test
-    public final void testDeregisterService() throws Exception {
-        RestResponseSuccess expectedResp = new RestResponseSuccess("Deregistration yielded code 0");
-        String expectedResult = objectMapper.writeValueAsString(expectedResp);
-
-        when(consulClient.deregisterService(Mockito.any())).thenReturn(0).thenThrow(Exception.class)
-            .thenThrow(httpException);
-
-        String actualResult = subject.deregisterService(mockedRequest, "srvc1");
-        assertTrue(actualResult.equals(expectedResult));
-
-        actualResult = subject.deregisterService(mockedRequest, "srvc1");
-        assertTrue(actualResult.contains("error"));
-
-        actualResult = subject.deregisterService(mockedRequest, "srvc1");
+    public final void testGetItemListForPageWrapper() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        user.setId(1000L);
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
+        String actualResult = 
+            subject.getItemListForPageWrapper(mockedRequest, "dc1", ConsulController.ConsulDataItem.SERVICE_INFO);
         assertTrue(actualResult.contains("error"));
+        
     }
-
 }
index 6517b68..4833c12 100644 (file)
@@ -27,6 +27,8 @@ import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.when;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -88,46 +90,13 @@ public class DeploymentHandlerControllerTest extends MockitoTestSuite {
     @Test
     public final void testPutDeployment_create() throws Exception {
         DeploymentRequestObject expectReq =
-            new DeploymentRequestObject("dep1", "dep1", null, "tenant1", "create");
-
+            new DeploymentRequestObject("dep1", "dep1", "create", null, "tenant1");
+        
         DeploymentResponseLinks expectLink = new DeploymentResponseLinks("self", "status");
         DeploymentResponse expectResp = new DeploymentResponse("req1", expectLink);
-
+        
         when(restClient.putDeployment(Matchers.anyString(), Matchers.anyString(),
-            Matchers.<DeploymentRequest>any())).thenReturn(expectResp).thenThrow(badReqError)
-                .thenThrow(srvcExistError).thenThrow(serverError).thenThrow(downStrmError)
-                .thenThrow(Exception.class);
-
-        String actualResp = subject.putDeployment(mockedRequest, expectReq);
-        assertTrue(actualResp.contains("req1"));
-
-        actualResp = subject.putDeployment(mockedRequest, expectReq);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.putDeployment(mockedRequest, expectReq);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.putDeployment(mockedRequest, expectReq);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.putDeployment(mockedRequest, expectReq);
-        assertTrue(actualResp.contains("error"));
-
-        actualResp = subject.putDeployment(mockedRequest, expectReq);
-        assertTrue(actualResp.contains("error"));
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public final void testPutDeployment_update() throws Exception {
-        DeploymentRequestObject expectReq =
-            new DeploymentRequestObject("dep1", "dep1", null, "tenant1", "update");
-
-        DeploymentResponseLinks expectLink = new DeploymentResponseLinks("self", "status");
-        DeploymentResponse expectResp = new DeploymentResponse("req1", expectLink);
-
-        when(restClient.updateDeployment(Matchers.anyString(), Matchers.anyString(),
-            Matchers.<DeploymentRequest>any())).thenReturn(expectResp).thenThrow(badReqError)
+            Matchers.<DeploymentRequest>any(), Matchers.<HttpServletRequest>any()) ).thenReturn(expectResp).thenThrow(badReqError)
                 .thenThrow(srvcExistError).thenThrow(serverError).thenThrow(downStrmError)
                 .thenThrow(Exception.class);
 
@@ -155,7 +124,7 @@ public class DeploymentHandlerControllerTest extends MockitoTestSuite {
 
         doNothing().doThrow(badReqError).doThrow(serverError).doThrow(downStrmError)
             .doThrow(notFoundError).doThrow(Exception.class).when(restClient)
-            .deleteDeployment(Matchers.anyString(), Matchers.anyString());
+            .deleteDeployment(Matchers.anyString(), Matchers.anyString(), Matchers.<HttpServletRequest>any());
 
         StringBuffer expectedStrBuff = new StringBuffer();
         expectedStrBuff.append("http://oom.s2.com");
index 01858ed..9cce55e 100644 (file)
@@ -31,6 +31,8 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.TreeSet;
@@ -54,6 +56,7 @@ import org.onap.ccsdk.dashboard.core.MockitoTestSuite;
 import org.onap.ccsdk.dashboard.exceptions.inventory.BlueprintParseException;
 import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceNotFoundException;
 import org.onap.ccsdk.dashboard.exceptions.inventory.ServiceTypeNotFoundException;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant;
 import org.onap.ccsdk.dashboard.model.inventory.Service;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceList;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceQueryParams;
@@ -63,10 +66,14 @@ import org.onap.ccsdk.dashboard.model.inventory.ServiceType;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeList;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummaryList;
 import org.onap.ccsdk.dashboard.rest.CloudifyClient;
 import org.onap.ccsdk.dashboard.rest.InventoryClient;
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
 import org.onap.portalsdk.core.domain.User;
+import org.onap.portalsdk.core.util.CacheManager;
+import org.onap.portalsdk.core.util.SystemProperties;
 import org.onap.portalsdk.core.web.support.AppUtils;
 import org.onap.portalsdk.core.web.support.UserUtils;
 import org.powermock.api.mockito.PowerMockito;
@@ -82,11 +89,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
 
 @RunWith(PowerMockRunner.class)
-@PrepareForTest({DashboardProperties.class})
 public class InventoryControllerTest extends MockitoTestSuite {
 
     @Mock
-    private CloudifyClient restClient;
+    private CloudifyClient cfyClient;
 
     @Mock
     private InventoryClient inventoryClient;
@@ -118,525 +124,293 @@ public class InventoryControllerTest extends MockitoTestSuite {
     HttpServletResponse mockedResponse;
 
     MockUser mockUser = new MockUser();
-    ServiceList deplList = null;
-    Service deplItem = null;
 
-    ServiceType bpItem = null;
-    ServiceTypeList bpList = null;
+    ServiceTypeSummary bpItem, bpItem2 = null;
+    ServiceTypeSummaryList bpList, bpList2 = null;
 
+    ServiceType bpItemFull = null;
+    ServiceTypeList bpItemFullList = null;
+    
     ServiceTypeRequest bpUploadItem = null;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         objectMapper.registerModule(new Jdk8Module());
-        getExpectedDeployments();
-        getExpectedBueprints();
+        getExpectedBlueprints();
         createBpUploadItem();
         mockedRequest = getMockedRequest();
         mockedResponse = getMockedResponse();
+        CacheManager testCache = new CacheManager();
+        Map<String, List<ServiceTypeSummary>> bpPerOwner = new HashMap<String, List<ServiceTypeSummary>>();
+        bpPerOwner.put("xyz1731", (List<ServiceTypeSummary>)bpList2.items);
+        testCache.putObject("owner_bp_map", bpPerOwner);
+        subject.setCacheManager(testCache); 
+        /*
+        PowerMockito.mockStatic(SystemProperties.class);
+        Mockito
+            .when(SystemProperties.getProperty("cache_switch"))
+            .thenReturn("1");
+        */
     }
 
-    public void getExpectedDeployments()
-        throws JsonParseException, JsonMappingException, IOException {
-
-        deplItem = new Service("dcae_dtiapi_1902", null, "1552335532348", "1552335532348", null,
-            "dummyVnfId", null, "dummyVnfType", "dummyLocation", "dcae_dtiapi_1902", null);
-        Collection<Service> items = new ArrayList<Service>();
-        items.add(deplItem);
-
-        String pageLinks =
-            "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}";
-        ServiceList.PaginationLinks paginationLinks =
-            objectMapper.readValue(pageLinks, ServiceList.PaginationLinks.class);
-        int totalCount = 1;
-        deplList = new ServiceList(items, totalCount, paginationLinks);
-
-    }
-
-    public void getExpectedBueprints()
+    public void getExpectedBlueprints()
         throws JsonParseException, JsonMappingException, IOException {
-        bpItem = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906,
+        bpItem = new ServiceTypeSummary.Builder().application("app1").component("comp1").
+        typeName("xyz1731-helm-1906").owner("xyz1731").typeVersion(1906).build();
+        
+        bpItem2 = new ServiceTypeSummary("xyz1731", "xyz1731-helm-1906", 1906, "app1", "comp1", "123-456-789",
+            "342343", true);
+        bpItemFull = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906,
             "tosca_definitions_version: cloudify_dsl_1_3", "", "app1", "comp1").build();
-        Collection<ServiceType> items = new ArrayList<ServiceType>();
+
+        Collection<ServiceTypeSummary> items = new ArrayList<ServiceTypeSummary>();
         items.add(bpItem);
 
+        Collection<ServiceTypeSummary> items2 = new ArrayList<ServiceTypeSummary>();
+        items2.add(bpItem2);
+        
         String pageLinks2 =
             "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}";
-        ServiceTypeList.PaginationLinks paginationLinks =
-            objectMapper.readValue(pageLinks2, ServiceTypeList.PaginationLinks.class);
+        ServiceTypeSummaryList.PaginationLinks paginationLinks =
+            objectMapper.readValue(pageLinks2, ServiceTypeSummaryList.PaginationLinks.class);
         int totalCount = 1;
-        bpList = new ServiceTypeList(items, totalCount, paginationLinks);
+        bpList = new ServiceTypeSummaryList(items, totalCount, paginationLinks);
+        bpList2 = new ServiceTypeSummaryList(items2, totalCount, paginationLinks);
     }
 
     public void createBpUploadItem() {
-        bpUploadItem = ServiceTypeRequest.from(bpItem);
+        bpUploadItem = ServiceTypeRequest.from(bpItemFull);
     }
 
     @After
     public void tearDown() throws Exception {
     }
 
+    @Test
+    public final void testGetOwnersByPage() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1);
+        String result = subject.getServiceTypesByPage(mockedRequest);
+        assertTrue(result.contains("xyz"));
+    }
+    
+    @Test
+    public final void testGetAllServiceTypeNames() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1);
+        String result = subject.getAllServiceTypeNames(mockedRequest);
+        assertTrue(result.contains("xyz"));        
+    }
+    
+    @Test
+    public final void testGetAllServiceTypeIds() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1);
+        String result = subject.getAllServiceTypeIds(mockedRequest);
+        assertTrue(result.contains("xyz"));        
+    }
+    
     @Test
     public final void testGetServiceTypesByPage() {
         User user = mockUser.mockUser();
         user.setLoginId("tester");
         MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
-        mockedRequest.addParameter("searchBy", "xyz");
+        //mockedRequest.addParameter("searchBy", "xyz");
         mockedRequest.addParameter("sortBy", "owner");
 
+        // # 1st case
         Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
-
-        Collection<ServiceType> items = bpList.items;
-
-        Stream<ServiceType> sampleStream1 = items.stream();
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
         Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1);
         String result = subject.getServiceTypesByPage(mockedRequest);
         assertTrue(result.contains("xyz"));
-
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-
+        
+        // # 2nd case
         HttpSession session = mockedRequest.getSession();
         HashMap<String, Boolean> comp_deploy_tab = new HashMap<String, Boolean>();
         comp_deploy_tab.put("comp1", true);
-
         Set<String> userApps = new TreeSet<String>();
         userApps.add("comp1");
-
         when(session.getAttribute("comp_access")).thenReturn(comp_deploy_tab);
         when(session.getAttribute("role_level")).thenReturn("app");
         when(session.getAttribute("authComponents")).thenReturn(userApps);
 
-        Stream<ServiceType> sampleStream2 = items.stream();
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
+        Stream<ServiceTypeSummary> sampleStream2 = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes())
             .thenReturn(sampleStream2);
+        /*
+        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
+        .thenReturn(sampleStream2);
+        */
         String result2 = subject.getServiceTypesByPage(mockedRequest);
         assertTrue(result2.contains("xyz"));
-    }
 
+    }
+    
     @Test
-    public final void testGetServiceTypesByPage_appl() {
+    public final void testGetServiceTypesByPage_appDevUser() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
         MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
-        mockedRequest.addParameter("sortBy", "application");
-
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> sampleStream1 = items.stream();
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
+        HttpSession session = mockedRequest.getSession();
+        HashMap<String, Boolean> comp_deploy_tab = new HashMap<String, Boolean>();
+        comp_deploy_tab.put("comp1", true);
+        Set<String> userApps = new TreeSet<String>();
+        userApps.add("comp1");
+        when(session.getAttribute("comp_access")).thenReturn(comp_deploy_tab);
+        when(session.getAttribute("role_level")).thenReturn("app_dev");
+        when(session.getAttribute("authComponents")).thenReturn(userApps);
 
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream);
 
-        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1);
         String result = subject.getServiceTypesByPage(mockedRequest);
         assertTrue(result.contains("xyz"));
+    }
+    
+    @Test
+    public final void testGetServiceTypesByPage_containsFilter() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        mockedRequest.addParameter("searchBy", "contains:xyz1731-helm-1906");
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
 
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream);
 
-        Stream<ServiceType> sampleStream2 = items.stream();
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
-            .thenReturn(sampleStream2);
-        String result2 = subject.getServiceTypesByPage(mockedRequest);
-        assertTrue(result2.contains("xyz"));
+        String result = subject.getServiceTypesByPage(mockedRequest);
+        assertTrue(result.contains("error"));
     }
+    
+    @Test
+    public final void testGetServiceTypesByPage_AllFilters() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        mockedRequest.addParameter("searchBy", "serviceRef:xyz1731-helm-1906;app:app1;comp:comp1;owner:xyz1731;");
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
+
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> sampleStream = items.stream();
+        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream);
 
+        String result = subject.getServiceTypesByPage(mockedRequest);
+        assertTrue(result.contains("xyz"));
+        
+    }
+    
     @Test
     public final void testGetServiceTypesByPage_comp() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");      
         MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
         mockedRequest.addParameter("sortBy", "component");
 
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> sampleStream1 = items.stream();
-
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
+        Collection<ServiceTypeSummary> items = bpList2.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
 
         Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1);
         String result = subject.getServiceTypesByPage(mockedRequest);
         assertTrue(result.contains("xyz"));
 
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-
-        Stream<ServiceType> sampleStream2 = items.stream();
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
-            .thenReturn(sampleStream2);
-        String result2 = subject.getServiceTypesByPage(mockedRequest);
-        assertTrue(result2.contains("xyz"));
     }
 
     @Test
     public final void testGetServiceTypesByPage_typeId() {
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");      
         MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
         mockedRequest.addParameter("sortBy", "typeId");
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> sampleStream1 = items.stream();
-
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
+        Collection<ServiceTypeSummary> items = bpList2.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
 
         Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1);
         String result = subject.getServiceTypesByPage(mockedRequest);
         assertTrue(result.contains("xyz"));
-
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-
-        Stream<ServiceType> sampleStream2 = items.stream();
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
-            .thenReturn(sampleStream2);
-        String result2 = subject.getServiceTypesByPage(mockedRequest);
-        assertTrue(result2.contains("xyz"));
     }
 
     @Test
     public final void testGetServiceTypesByPage_typeName() {
-
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");      
         MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
         mockedRequest.addParameter("sortBy", "typeName");
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> sampleStream1 = items.stream();
-
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
-
+        Collection<ServiceTypeSummary> items = bpList2.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
         Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1);
         String result = subject.getServiceTypesByPage(mockedRequest);
         assertTrue(result.contains("xyz"));
-
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-
-        Stream<ServiceType> sampleStream2 = items.stream();
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
-            .thenReturn(sampleStream2);
-        String result2 = subject.getServiceTypesByPage(mockedRequest);
-        assertTrue(result2.contains("xyz"));
-
     }
 
     @Test
     public final void testGetServiceTypesByPage_typeVer() {
-
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");      
         MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
         mockedRequest.addParameter("sortBy", "typeVersion");
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> sampleStream1 = items.stream();
-
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
+        Collection<ServiceTypeSummary> items = bpList2.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
 
         Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1);
         String result = subject.getServiceTypesByPage(mockedRequest);
         assertTrue(result.contains("xyz"));
-
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-
-        Stream<ServiceType> sampleStream2 = items.stream();
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
-            .thenReturn(sampleStream2);
-        String result2 = subject.getServiceTypesByPage(mockedRequest);
-        assertTrue(result2.contains("xyz"));
-
     }
 
     @Test
     public final void testGetServiceTypesByPage_created() {
-
+        User user = mockUser.mockUser();
+        user.setLoginId("tester");      
         MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
         mockedRequest.addParameter("sortBy", "created");
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> sampleStream1 = items.stream();
-
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
+        Collection<ServiceTypeSummary> items = bpList2.items;
+        Stream<ServiceTypeSummary> sampleStream1 = items.stream();
 
         Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream1);
         String result = subject.getServiceTypesByPage(mockedRequest);
         assertTrue(result.contains("xyz"));
-
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-
-        Stream<ServiceType> sampleStream2 = items.stream();
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
-            .thenReturn(sampleStream2);
-        String result2 = subject.getServiceTypesByPage(mockedRequest);
-        assertTrue(result2.contains("xyz"));
     }
 
-    @Test
-    public final void testGetServiceTypesByPage_Auth() {
-
-        User user = mockUser.mockUser();
-        user.setLoginId("tester");
-        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
-        mockedRequest.addParameter("searchBy", "xyz");
-
-        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> sampleStream = items.stream();
-
-        HttpSession session = mockedRequest.getSession();
-        HashMap<String, Boolean> comp_deploy_tab = new HashMap<String, Boolean>();
-        comp_deploy_tab.put("comp1", true);
-
-        Set<String> userApps = new TreeSet<String>();
-        userApps.add("comp1");
-
-        when(session.getAttribute("comp_access")).thenReturn(comp_deploy_tab);
-        when(session.getAttribute("role_level")).thenReturn("ops");
-        when(session.getAttribute("authComponents")).thenReturn(userApps);
-
-        Mockito.when(inventoryClient.getServiceTypes(Matchers.<ServiceTypeQueryParams>any()))
-            .thenReturn(sampleStream);
-        String result = subject.getServiceTypesByPage(mockedRequest);
-        assertTrue(result.contains("xyz"));
-    }
 
     @SuppressWarnings("unchecked")
     @Test
     public final void testGetServiceTypesByPage_Exception() {
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> sampleStream = items.stream();
-        when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
         when(inventoryClient.getServiceTypes()).thenThrow(RestClientException.class)
-            .thenThrow(httpException).thenReturn(sampleStream);
+            .thenThrow(httpException);
 
         String errResp = subject.getServiceTypesByPage(mockedRequest);
         assertTrue(errResp.contains("error"));
 
         errResp = subject.getServiceTypesByPage(mockedRequest);
         assertTrue(errResp.contains("error"));
-
-        String result = subject.getServiceTypesByPage(mockedRequest);
-        assertTrue(result.contains("xyz"));
-    }
-
-    @Test
-    public final void testGetServiceTypesByPage_Filter() {
-        User user = mockUser.mockUser();
-        user.setLoginId("tester");
-        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
-        mockedRequest.addParameter("searchBy", "xyz");
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito.when(UserUtils.getUserSession(mockedRequest)).thenReturn(user);
-
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> sampleStream = items.stream();
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
-        Mockito.when(inventoryClient.getServiceTypes()).thenReturn(sampleStream);
-
-        String result = subject.getServiceTypesByPage(mockedRequest);
-        assertTrue(result.contains("xyz"));
     }
 
-    @Test
-    public final void testGetServicesByPage_auth() throws IOException {
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-        MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest();
-        mockedRequest1.addParameter("searchBy", "dti");
 
-        Collection<Service> items = deplList.items;
-
-        HttpSession session = mockedRequest1.getSession();
-        HashMap<String, Boolean> comp_deploy_tab = new HashMap<String, Boolean>();
-        comp_deploy_tab.put("dcae", true);
-
-        Set<String> userApps = new TreeSet<String>();
-        userApps.add("dcae");
-
-        when(session.getAttribute("comp_access")).thenReturn(comp_deploy_tab);
-        when(session.getAttribute("role_level")).thenReturn("app");
-        when(session.getAttribute("authComponents")).thenReturn(userApps);
-
-        Stream<Service> sampleStream1 = items.stream();
-        Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1);
-
-        String result1 = subject.getServicesByPage(mockedRequest1);
-        assertTrue(result1.contains("dti"));
-
-    }
-
-    @Test
-    public final void testGetServicesByPage_auth_ops() throws IOException {
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-        MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest();
-        mockedRequest1.addParameter("searchBy", "dti");
-
-        Collection<Service> items = deplList.items;
-
-        HttpSession session = mockedRequest1.getSession();
-        HashMap<String, Boolean> comp_deploy_tab = new HashMap<String, Boolean>();
-        comp_deploy_tab.put("dcae", true);
-
-        Set<String> userApps = new TreeSet<String>();
-        userApps.add("dcae");
-
-        when(session.getAttribute("comp_access")).thenReturn(comp_deploy_tab);
-        when(session.getAttribute("role_level")).thenReturn("ops");
-        when(session.getAttribute("authComponents")).thenReturn(userApps);
-
-        Stream<Service> sampleStream1 = items.stream();
-        Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1);
-
-        String result1 = subject.getServicesByPage(mockedRequest1);
-        assertTrue(result1.contains("dti"));
-
-    }
-
-    @Test
-    public final void testGetServicesByPage() throws IOException {
-        /*
-         * User user = mockUser.mockUser(); user.setLoginId("tester");
-         */
-        MockHttpServletRequestWrapper mockedRequest1 = getMockedRequest();
-        mockedRequest1.addParameter("searchBy", "dti");
-        mockedRequest1.addParameter("sortBy", "deploymentRef");
-
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
-
-        Collection<Service> items = deplList.items;
-
-        Stream<Service> sampleStream1 = items.stream();
-        Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1);
-
-        String result1 = subject.getServicesByPage(mockedRequest1);
-        assertTrue(result1.contains("dti"));
-    }
-
-    @Test
-    public final void testGetServicesByPage_sort_serviceId() throws IOException {
-
-        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
-        mockedRequest.addParameter("sortBy", "serviceId");
-
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
-
-        Collection<Service> items = deplList.items;
-
-        Stream<Service> sampleStream1 = items.stream();
-        Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream1);
-
-        String result = subject.getServicesByPage(mockedRequest);
-        assertTrue(result.contains("dti"));
-
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-
-        Stream<Service> sampleStream2 = items.stream();
-        Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream2);
-
-        String result2 = subject.getServicesByPage(mockedRequest);
-        assertTrue(result2.contains("dti"));
-    }
-
-    @Test
-    public final void testGetServicesByPage_sort_created() throws IOException {
-        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
-        mockedRequest.addParameter("sortBy", "created");
-
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
-
-        Collection<Service> items = deplList.items;
-
-        Stream<Service> sampleStream = items.stream();
-        Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream);
-
-        String result = subject.getServicesByPage(mockedRequest);
-        assertTrue(result.contains("dti"));
-
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-
-        Stream<Service> sampleStream2 = items.stream();
-        Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream2);
-
-        String result2 = subject.getServicesByPage(mockedRequest);
-        assertTrue(result2.contains("dti"));
-
-    }
-
-    @Test
-    public final void testGetServicesByPage_sort_modified() throws IOException {
-
-        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
-        mockedRequest.addParameter("sortBy", "modified");
-
-        PowerMockito.mockStatic(DashboardProperties.class);
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("os");
-
-        Collection<Service> items = deplList.items;
-
-        Stream<Service> sampleStream = items.stream();
-        Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream);
-
-        String result = subject.getServicesByPage(mockedRequest);
-        assertTrue(result.contains("dti"));
-
-        Mockito
-            .when(DashboardProperties.getPropertyDef(DashboardProperties.CONTROLLER_TYPE, "auth"))
-            .thenReturn("auth");
-
-        Stream<Service> sampleStream2 = items.stream();
-        Mockito.when(inventoryClient.getServices()).thenReturn(sampleStream2);
-
-        String result2 = subject.getServicesByPage(mockedRequest);
-        assertTrue(result2.contains("dti"));
-    }
 
     @SuppressWarnings("unchecked")
     @Test
@@ -670,38 +444,36 @@ public class InventoryControllerTest extends MockitoTestSuite {
             .thenThrow(BlueprintParseException.class).thenThrow(httpException)
             .thenThrow(Exception.class).thenReturn(null);
 
-        String actual1 = subject.updateServiceTypeBlueprint(mockedRequest, bpItem);
+        String actual1 = subject.updateServiceTypeBlueprint(mockedRequest, bpItemFull);
         assertTrue(actual1.contains("error"));
 
-        String actual2 = subject.updateServiceTypeBlueprint(mockedRequest, bpItem);
+        String actual2 = subject.updateServiceTypeBlueprint(mockedRequest, bpItemFull);
         assertTrue(actual2.contains("error"));
 
-        String actual3 = subject.updateServiceTypeBlueprint(mockedRequest, bpItem);
+        String actual3 = subject.updateServiceTypeBlueprint(mockedRequest, bpItemFull);
         assertTrue(actual3.contains("error"));
 
-        String actual = subject.updateServiceTypeBlueprint(mockedRequest, bpItem);
+        String actual = subject.updateServiceTypeBlueprint(mockedRequest, bpItemFull);
         assertEquals(expected, actual);
     }
 
-    @Test
-    public final void testDeleteService() throws Exception {
-        String expected = "{\"202\": \"OK\"}";
-        doNothing().doThrow(serviceException).doThrow(Exception.class).when(inventoryClient)
-            .deleteService(Matchers.anyString());
-
-        String actual = subject.deleteService("srvcId", mockedRequest, mockedResponse);
-        assertEquals(expected, actual);
-
-        actual = subject.deleteService("srvcId", mockedRequest, mockedResponse);
-        assertTrue(actual.contains("error"));
-
-        actual = subject.deleteService("srvcId", mockedRequest, mockedResponse);
-        assertTrue(actual.contains("error"));
-    }
-
     @Test
     public final void testDeleteServiceType() throws Exception {
-        String expected = "{\"202\": \"OK\"}";
+        //String expected = "{\"202\": \"OK\"}";
+        String expected = "{\"204\": \"Blueprint deleted\"}";
+        List<CloudifyDeployedTenant> deplForBp = new ArrayList<>();
+        deplForBp.clear();
+        Mockito.when(cfyClient.getDeploymentForBlueprint(Matchers.<String>any()))
+        .thenReturn(deplForBp);
+        
+        List<ServiceRef> srvcRefList = new ArrayList<>();
+        srvcRefList.clear();
+        int itemCnt = 0;
+        ServiceRefList mockSvcRefList = new ServiceRefList(srvcRefList, itemCnt);
+
+        Mockito.when(inventoryClient.getServicesForType(Matchers.<ServiceQueryParams>any()))
+            .thenReturn(mockSvcRefList);
+        
         doNothing().doThrow(serviceTypeException).doThrow(Exception.class).when(inventoryClient)
             .deleteServiceType(Matchers.anyString());
 
@@ -715,10 +487,24 @@ public class InventoryControllerTest extends MockitoTestSuite {
         assertTrue(actual.contains("error"));
     }
 
+    @Test
+    public final void testDeleteServiceType_withDepl() throws Exception {
+        CloudifyDeployedTenant mockCfyDeplTen = 
+            new CloudifyDeployedTenant("id1", "tenant", "45435435", "54543534");
+        
+        List<CloudifyDeployedTenant> deplForBp = new ArrayList<>();
+        deplForBp.add(mockCfyDeplTen);
+        Mockito.when(cfyClient.getDeploymentForBlueprint(Matchers.<String>any()))
+        .thenReturn(deplForBp);
+        
+        String actual = subject.deleteServiceType("srvcId", mockedRequest, mockedResponse);
+        assertTrue(actual.contains("error"));
+    }
+    
     @SuppressWarnings("unchecked")
     @Test
     public final void testViewServiceTypeBlueprintContentById() throws Exception {
-        Optional<ServiceType> expected = Optional.of(bpItem);
+        Optional<ServiceType> expected = Optional.of(bpItemFull);
         when(inventoryClient.getServiceType(Matchers.anyString())).thenReturn(expected)
             .thenThrow(httpException).thenThrow(Exception.class);
 
diff --git a/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/model/ControllerOpsToolsTest.java b/ccsdk-app-common/src/test/java/org/onap/ccsdk/dashboard/model/ControllerOpsToolsTest.java
deleted file mode 100644 (file)
index 001df8d..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
- * 
- * Modifications Copyright (C) 2019 IBM.
- * ================================================================================
- * 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.
- * ============LICENSE_END=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-package org.onap.ccsdk.dashboard.model;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-public class ControllerOpsToolsTest {
-       
-       ControllerOpsTools co;
-       private String id="123";
-    private String url="http//google.com";
-
-       @Test
-       public void testControllerOpsTools() {
-               ControllerOpsTools co= new ControllerOpsTools();
-               ControllerOpsTools co1= new ControllerOpsTools(id,url);
-               assertEquals("123",co1.getId());
-               assertEquals("http//google.com",co1.getUrl());
-       }
-
-}
index a5c5cf8..68223da 100644 (file)
@@ -31,8 +31,14 @@ import static org.mockito.Mockito.when;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 import org.junit.Before;
 import org.junit.Ignore;
@@ -43,28 +49,32 @@ import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
-import org.onap.ccsdk.dashboard.model.CloudifyBlueprint;
-import org.onap.ccsdk.dashboard.model.CloudifyBlueprintList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenant;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployedTenantList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeployment;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentList;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyDeploymentUpdateResponse;
-import org.onap.ccsdk.dashboard.model.CloudifyEvent;
-import org.onap.ccsdk.dashboard.model.CloudifyEventList;
-import org.onap.ccsdk.dashboard.model.CloudifyEventList.Metadata;
-import org.onap.ccsdk.dashboard.model.CloudifyExecution;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionList;
-import org.onap.ccsdk.dashboard.model.CloudifyExecutionRequest;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeId;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeIdList;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstance;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceId;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceIdList;
-import org.onap.ccsdk.dashboard.model.CloudifyNodeInstanceList;
-import org.onap.ccsdk.dashboard.model.CloudifyTenantList;
+import org.onap.ccsdk.dashboard.core.MockitoTestSuite;
+import org.onap.ccsdk.dashboard.core.MockitoTestSuite.MockHttpServletRequestWrapper;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprint;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyBlueprintList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenant;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployedTenantList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeploymentList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEvent;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyEventList.Metadata;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecution;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyExecutionRequest;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeId;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeIdList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstance;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceId;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceIdList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyNodeInstanceList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPlugin;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyPluginList;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyTenantList;
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
+import org.onap.portalsdk.core.util.CacheManager;
 import org.powermock.api.mockito.PowerMockito;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
@@ -83,23 +93,27 @@ import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
 
 @RunWith(PowerMockRunner.class)
 @PrepareForTest({DashboardProperties.class})
-public class CloudifyRestClientImplTest {
+public class CloudifyRestClientImplTest extends MockitoTestSuite {
 
     @Mock
     RestTemplate mockRest;
 
     @InjectMocks
     CloudifyRestClientImpl subject = new CloudifyRestClientImpl();
-
-    protected final ObjectMapper objectMapper = new ObjectMapper();
+    
+    HttpServletRequest mockedRequest;
+    HttpServletResponse mockedResponse;
+    protected final static ObjectMapper objectMapper = new ObjectMapper();
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         objectMapper.registerModule(new Jdk8Module());
         PowerMockito.mockStatic(DashboardProperties.class);
-        when(DashboardProperties.getControllerProperty("dev",
-            DashboardProperties.CONTROLLER_SUBKEY_URL)).thenReturn("https://orcl.com");
+        when(DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_CLOUDIFY_URL)).thenReturn("https://orcl.com");
+        CacheManager testCache = new CacheManager();
+        subject.setCacheManager(testCache); 
         this.subject.init();
     }
 
@@ -287,32 +301,11 @@ public class CloudifyRestClientImplTest {
         assertTrue(actualResult.items.get(0).id.equals("node_instance_id1"));
     }
 
-    @Test
-    public final void testGetTenantInfoFromDeploy() {
-
-        CloudifyDeployedTenant cldDeplTenant = new CloudifyDeployedTenant("id1", "bp1", "tenant1");
-        List<CloudifyDeployedTenant> cldDeplTenantItems = new ArrayList<CloudifyDeployedTenant>();
-        cldDeplTenantItems.add(cldDeplTenant);
-        CloudifyDeployedTenantList cldDeployedTenantList =
-            new CloudifyDeployedTenantList(cldDeplTenantItems, null);
-
-        ResponseEntity<CloudifyDeployedTenantList> response =
-            new ResponseEntity<CloudifyDeployedTenantList>(cldDeployedTenantList, HttpStatus.OK);
-
-        when(mockRest.exchange(Matchers.contains("deployments"), Matchers.eq(HttpMethod.GET),
-            Matchers.<HttpEntity<?>>any(),
-            Matchers.<ParameterizedTypeReference<CloudifyDeployedTenantList>>any()))
-                .thenReturn(response);
-
-        CloudifyDeployedTenantList actualResults = subject.getTenantInfoFromDeploy("tenant1");
-        assertTrue(actualResults.items.get(0).blueprint_id.equals("bp1"));
-    }
-
     @Test
     public void testGetExecutions() {
         CloudifyExecution cldExecution =
-            new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1",
-                "tenant1", "error", "execution_id1", null, false, false);
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, 
+                "bp1", "id1","tenant1", "error", "execution_id1", null);
 
         List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
 
@@ -336,8 +329,8 @@ public class CloudifyRestClientImplTest {
     @Test
     public void testGetExecutionsSummary() {
         CloudifyExecution cldExecution =
-            new CloudifyExecution("successful", "created_at", "install", false, "bp1", "id1",
-                "tenant1", "error", "execution_id1", null, false, false);
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
 
         List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
 
@@ -361,8 +354,8 @@ public class CloudifyRestClientImplTest {
 
     @Test
     public void testStartExecution() {
-        CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "install",
-            false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false);
+        CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "ended-at", "install",
+            false, "bp1", "id1", "tenant1", "error", "execution_id1", null);
 
         Map<String, Object> params = new HashMap<String, Object>();
         params.put("key1", "value1");
@@ -377,30 +370,11 @@ public class CloudifyRestClientImplTest {
         assertTrue(actualResult.status.equals("successful"));
     }
 
-    @Test
-    public void testUpdateDeployment() {
-        CloudifyDeploymentUpdateRequest cfyDeployUpdateReq =
-            new CloudifyDeploymentUpdateRequest("deployment_id", "update", false, false,
-                "node_instance_id1", "4", "1000", "image", 2, "my_container");
-
-        CloudifyDeploymentUpdateResponse cfyDeployUpdateResp = new CloudifyDeploymentUpdateResponse(
-            "terminated", "created_at", "update", false, "blueprint_id", "deployment_id", "", "id1",
-            null, "tenant1", "junit", false, "resource_availability");
-
-        when(mockRest.postForObject(Matchers.anyString(), Matchers.<HttpEntity<?>>any(),
-            Matchers.<Class<CloudifyDeploymentUpdateResponse>>any()))
-                .thenReturn(cfyDeployUpdateResp);
-
-        CloudifyDeploymentUpdateResponse actualResult =
-            subject.updateDeployment(cfyDeployUpdateReq);
-        assertTrue(actualResult.status.equals("terminated"));
-    }
-
     @Test
     @Ignore
     public void testCancelExecution() {
-        CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "install",
-            false, "bp1", "id1", "tenant1", "error", "execution_id1", null, false, false);
+        CloudifyExecution cfyExecObj = new CloudifyExecution("successful", "created_at", "end_at", "install",
+            false, "bp1", "id1", "tenant1", "error", "execution_id1", null);
 
         Map<String, Object> params = new HashMap<String, Object>();
         params.put("key1", "value1");
@@ -421,7 +395,6 @@ public class CloudifyRestClientImplTest {
     }
 
     @Test
-    @Ignore
     public void testGetBlueprint() {
         CloudifyBlueprint cldBp =
             new CloudifyBlueprint("file1", "description1", "343242", "3423423", "id1", null);
@@ -441,16 +414,39 @@ public class CloudifyRestClientImplTest {
 
         doReturn(response).when(mockRest).exchange(Matchers.anyString(),
             Matchers.eq(HttpMethod.GET), Matchers.<HttpEntity<?>>any(),
-            Matchers.<Class<CloudifyBlueprintList>>any());
+            Matchers.<ParameterizedTypeReference<CloudifyBlueprintList>>any());
 
         CloudifyBlueprintList actualResult = subject.getBlueprint("id1", "tenant1");
         assertTrue(actualResult.items.get(0).id.equals("id1"));
     }
 
     @Test
-    @Ignore
     public void testGetDeployments() {
+        CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant");
 
+        List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>();
+        cfyDeployItems.add(cldDeployment);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata);
+
+        ResponseEntity<CloudifyDeploymentList> response =
+            new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK);
+
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any()))
+                .thenReturn(response);
+        
+        CloudifyDeploymentList actualResult = subject.getDeployments("tenant", 10, 0);
+        assertTrue(actualResult.items.get(0).id.equals("id"));
+    }
+    
+    @Test
+    public void testGetDeployments_from_cache() {
         CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id",
             "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant");
 
@@ -466,11 +462,380 @@ public class CloudifyRestClientImplTest {
         ResponseEntity<CloudifyDeploymentList> response =
             new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK);
 
-        when(mockRest.exchange(Matchers.contains("deploy"), Matchers.eq(HttpMethod.GET),
-            Matchers.<HttpEntity<?>>any(), Matchers.<Class<CloudifyDeploymentList>>any()))
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any()))
                 .thenReturn(response);
+        
+        List<CloudifyDeployment> actualResult = subject.getDeployments("tenant", 10, 0, true, true);
+        assertTrue(actualResult.get(0).id.equals("id"));
+    }
+    
+    @Test
+    public void testGetDeploymentForBlueprint() {
+        CloudifyDeployedTenant cfyDepTenant = 
+            new CloudifyDeployedTenant("id", "tenant", "created_at", "updated_at");
+        List<CloudifyDeployedTenant> cfyDepTenantList = new ArrayList<>();
+        cfyDepTenantList.add(cfyDepTenant);
+            
+        CloudifyDeployedTenantList.Metadata.Pagination pageObj =
+            new CloudifyDeployedTenantList.Metadata.Pagination(1, 0, 1);
+        CloudifyDeployedTenantList.Metadata metadata = new CloudifyDeployedTenantList.Metadata(pageObj);
+
+        CloudifyDeployedTenantList cldDeployList = new CloudifyDeployedTenantList(cfyDepTenantList, metadata);
 
-        CloudifyDeploymentList actualResult = subject.getDeployments();
+        ResponseEntity<CloudifyDeployedTenantList> response =
+            new ResponseEntity<CloudifyDeployedTenantList>(cldDeployList, HttpStatus.OK);
+
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifyDeployedTenantList>>any()))
+                .thenReturn(response);
+        
+        List<CloudifyDeployedTenant> actuals = subject.getDeploymentForBlueprint("bpId");
+        assertTrue(actuals.get(0).id.equals("id"));
+    }
+    
+    @Test
+    public void testGetDeploymentResource() {        
+        CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant");
+
+        List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>();
+        cfyDeployItems.add(cldDeployment);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata);
+
+        ResponseEntity<CloudifyDeploymentList> response =
+            new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK);
+
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any()))
+                .thenReturn(response);
+
+        CloudifyDeployment actualResult = subject.getDeploymentResource("id", "tenant");  
+        assertTrue(actualResult.id.equals("id"));
+    }
+    
+    @Test
+    public void testGetNodeInstanceDetails() {
+        CloudifyNodeInstance cfyNodeInstance = new CloudifyNodeInstance("id1", null);
+
+        List<CloudifyNodeInstance> cfyNodeInstanceItems = new ArrayList<CloudifyNodeInstance>();
+        cfyNodeInstanceItems.add(cfyNodeInstance);
+
+        CloudifyNodeInstanceList cfyNodeInstList =
+            new CloudifyNodeInstanceList(cfyNodeInstanceItems, null);
+
+        ResponseEntity<CloudifyNodeInstanceList> response2 =
+            new ResponseEntity<CloudifyNodeInstanceList>(cfyNodeInstList, HttpStatus.OK);
+        when(mockRest.exchange(Matchers.contains("node-instances"), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifyNodeInstanceList>>any()))
+                .thenReturn(response2);       
+        
+        CloudifyNodeInstanceList actualResult = 
+            subject.getNodeInstanceDetails("id", "tenant");
+        assertTrue(actualResult.items.get(0).id.equals("id1"));
+    }
+    
+    @Test
+    public void testGetNodeInstances() {
+        CloudifyNodeInstanceId cfyNodeInstance = new CloudifyNodeInstanceId("id1");
+
+        List<CloudifyNodeInstanceId> cfyNodeInstanceItems = new ArrayList<CloudifyNodeInstanceId>();
+        cfyNodeInstanceItems.add(cfyNodeInstance);
+
+        CloudifyNodeInstanceIdList cfyNodeInstList =
+            new CloudifyNodeInstanceIdList(cfyNodeInstanceItems, null);
+
+        ResponseEntity<CloudifyNodeInstanceIdList> response2 =
+            new ResponseEntity<CloudifyNodeInstanceIdList>(cfyNodeInstList, HttpStatus.OK);
+        when(mockRest.exchange(Matchers.contains("node-instances"), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifyNodeInstanceIdList>>any()))
+                .thenReturn(response2);       
+        
+        CloudifyNodeInstanceIdList actualResult = 
+            subject.getNodeInstances("id", "tenant");
+        assertTrue(actualResult.items.get(0).id.equals("id1"));
+    }
+    
+    
+    @Test    
+    public void testGetExecutionsSummaryPerTenant() {
+        CloudifyExecution cldExecution =
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
+
+        List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
+
+        cldExecutionList.add(cldExecution);
+
+        CloudifyExecutionList cloudifyExecutionList =
+            new CloudifyExecutionList(cldExecutionList, null);
+
+        ResponseEntity<CloudifyExecutionList> response =
+            new ResponseEntity<CloudifyExecutionList>(cloudifyExecutionList, HttpStatus.OK);
+
+        when(mockRest.exchange(Matchers.contains("include"), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifyExecutionList>>any()))
+                .thenReturn(response);
+
+        CloudifyExecutionList actualResult =
+            subject.getExecutionsSummaryPerTenant("tenant1");
+        assertTrue(actualResult.items.get(0).id.contains("id1"));
+    }
+    
+    @Test
+    public void testGetExecutionIdSummary() {
+        CloudifyExecution cldExecution =
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
+        ResponseEntity<CloudifyExecution> response =
+            new ResponseEntity<CloudifyExecution>(cldExecution, HttpStatus.OK);
+        when(mockRest.exchange(Matchers.contains("include"), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifyExecution>>any()))
+                .thenReturn(response);
+        CloudifyExecution actuals = subject.getExecutionIdSummary("execution_id1", "tenant");
+        assertTrue(actuals.id.contains("execution_id1"));
+    }
+    
+    @Test
+    public void testGetInstallExecutionSummary() {
+        CloudifyExecution cldExecution =
+            new CloudifyExecution("successful", "created_at", "ended_at", "install", false, "bp1", "id1",
+                "tenant1", "error", "execution_id1", null);
+
+        List<CloudifyExecution> cldExecutionList = new ArrayList<CloudifyExecution>();
+
+        cldExecutionList.add(cldExecution);
+
+        CloudifyExecutionList cloudifyExecutionList =
+            new CloudifyExecutionList(cldExecutionList, null);
+
+        ResponseEntity<CloudifyExecutionList> response =
+            new ResponseEntity<CloudifyExecutionList>(cloudifyExecutionList, HttpStatus.OK);
+
+        when(mockRest.exchange(Matchers.contains("include"), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifyExecutionList>>any()))
+                .thenReturn(response);
+
+        CloudifyExecutionList actualResult =
+            subject.getInstallExecutionSummary("id1", "tenant1");
+        assertTrue(actualResult.items.get(0).id.contains("id1"));
+    }
+    
+    @Test
+    public void testViewBlueprint() {
+        byte[] outArr =  "Any String you want".getBytes();
+        ResponseEntity<byte[]> response = 
+            new ResponseEntity<byte[]>(outArr, HttpStatus.OK);
+
+        doReturn(response).when(mockRest).exchange(Matchers.anyString(),
+            Matchers.eq(HttpMethod.GET), Matchers.<HttpEntity<?>>any(),
+            Matchers.<Class<?>>any());
+        
+        subject.viewBlueprint("tenant1", "id1");
+    }
+    
+    @Test
+    public void testGetDeploymentNamesWithFilter() throws Exception {
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        //mockedRequest.addParameter("filters", filterStr);
+        //mockedRequest.addParameter("sort", "name");
+        Set<String> userRoleSet = new HashSet<String>();
+        Set<String> userApps = new TreeSet<>();
+        userRoleSet.add("Standard User");
+        userRoleSet.add("ECOMPC_DCAE_WRITE");
+        userApps.add("dcae");
+        
+        Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet);
+        Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps);
+        
+        String tenantsList =
+            "{\"items\": [{\"id\": 1, \"dName\": null, \"name\": \"default_tenant\"}, {\"id\": 2, \"dName\": null, \"name\": \"dyh1b1902\"}], \"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}";
+        CloudifyTenantList sampleData = null;
+        try {
+            sampleData = objectMapper.readValue(tenantsList, CloudifyTenantList.class);
+        } catch (Exception e) {
+        }
+
+        ResponseEntity<CloudifyTenantList> response1 =
+            new ResponseEntity<CloudifyTenantList>(sampleData, HttpStatus.OK);
+
+        
+        CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant");
+
+        List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>();
+        cfyDeployItems.add(cldDeployment);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata);
+
+        ResponseEntity<CloudifyDeploymentList> response2 =
+            new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK);
+
+        Mockito
+        .when(mockRest.exchange(Matchers.contains("tenants"), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifyTenantList>>any()))
+        .thenReturn(response1);
+
+        Mockito.when(mockRest.exchange(Matchers.contains("deployments"), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any()))
+                .thenReturn(response2);        
+        
+        List<String> actual = subject.getDeploymentNamesWithFilter(mockedRequest);
+        assertTrue(actual.size() > 0);
+    }
+    
+    @Test
+    public void testGetDeploymentsWithFilter() throws Exception {
+        MockHttpServletRequestWrapper mockedRequest = getMockedRequest();
+        //mockedRequest.addParameter("filters", filterStr);
+        //mockedRequest.addParameter("sort", "name");
+        Set<String> userRoleSet = new HashSet<String>();
+        Set<String> userApps = new TreeSet<>();
+        userRoleSet.add("Standard User");
+        userRoleSet.add("ECOMPC_DCAE_WRITE");
+        userApps.add("dcae");
+        
+        Mockito.when(mockedRequest.getAttribute("userRoles")).thenReturn(userRoleSet);
+        Mockito.when(mockedRequest.getAttribute("userApps")).thenReturn(userApps);
+        
+        String tenantsList =
+            "{\"items\": [{\"id\": 1, \"dName\": null, \"name\": \"default_tenant\"}, {\"id\": 2, \"dName\": null, \"name\": \"dyh1b1902\"}], \"metadata\": {\"pagination\": {\"total\": 2, \"offset\": 0, \"size\": 0}}}";
+        CloudifyTenantList sampleData = null;
+        try {
+            sampleData = objectMapper.readValue(tenantsList, CloudifyTenantList.class);
+        } catch (Exception e) {
+        }
+
+        ResponseEntity<CloudifyTenantList> response1 =
+            new ResponseEntity<CloudifyTenantList>(sampleData, HttpStatus.OK);
+
+        
+        CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant");
+
+        List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>();
+        cfyDeployItems.add(cldDeployment);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata);
+
+        ResponseEntity<CloudifyDeploymentList> response2 =
+            new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK);
+
+        Mockito
+        .when(mockRest.exchange(Matchers.contains("tenants"), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifyTenantList>>any()))
+        .thenReturn(response1);
+
+        Mockito.when(mockRest.exchange(Matchers.contains("deployments"), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any()))
+                .thenReturn(response2);
+        
+        List<CloudifyDeployment> actuals = subject.getDeploymentsWithFilter(mockedRequest);
+        assertTrue(actuals.size() > 0);
+    }
+    
+    @Test
+    public void testGetSecret() {
+        String secretTokenStr =
+            "{\"created_at\": \"created_ts\", \"key\": \"acl_key\", \"updated_at\": \"updated_ts\", \"value\": \"acl_token_val\", \"visibility\": \"global\", \"is_hidden_value\": \"false\", \"tenant_name\": \"tenant\", \"resource_availability\": \"rsrc\"}";          
+        CloudifySecret sampleData = null;
+        try {
+            sampleData = objectMapper.readValue(secretTokenStr, CloudifySecret.class);
+        } catch (Exception e) {
+            
+        }
+        
+        ResponseEntity<CloudifySecret> response =
+            new ResponseEntity<CloudifySecret>(sampleData, HttpStatus.OK);
+        
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifySecret>>any()))
+                .thenReturn(response);
+        
+        CloudifySecret actuals = subject.getSecret("acl_key", "tenant");
+        assertTrue(actuals.getKey().equals("acl_key"));
+    }
+    
+    @Test
+    public void testDeleteBlueprint() {
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.DELETE),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifyBlueprint>>any())).thenReturn(null);
+        subject.deleteBlueprint("bp", "tenant");
+    }
+    
+    @Test
+    public void testGetPlugins() {
+        CloudifyPlugin sampleData = 
+            new CloudifyPlugin("plugin1", "202001", "linux", "linux_k8s_plugin", "20200801");
+
+        List<CloudifyPlugin> cfyPlugins = new ArrayList<CloudifyPlugin>();
+        cfyPlugins.add(sampleData);
+
+        CloudifyPluginList.Metadata.Pagination pageObj =
+            new CloudifyPluginList.Metadata.Pagination(1, 0, 1);
+        CloudifyPluginList.Metadata metadata = new CloudifyPluginList.Metadata(pageObj);
+
+        CloudifyPluginList cfyPluginList = new CloudifyPluginList(cfyPlugins, metadata);
+        ResponseEntity<CloudifyPluginList> response =
+            new ResponseEntity<CloudifyPluginList>(cfyPluginList, HttpStatus.OK);
+        
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifyPluginList>>any()))
+                .thenReturn(response);
+        
+        CloudifyPluginList actuals = subject.getPlugins();
+        assertTrue(actuals.items.get(0).package_name.equals("plugin1"));
+    }
+    
+    @Test
+    public void testGetDeploymentInputs() {
+        CloudifyDeployment cldDeployment = new CloudifyDeployment("description", "blueprint_id",
+            "created_at", "updated_at", "id", null, null, null, null, null, null, null, "tenant");
+
+        List<CloudifyDeployment> cfyDeployItems = new ArrayList<CloudifyDeployment>();
+        cfyDeployItems.add(cldDeployment);
+
+        CloudifyDeploymentList.Metadata.Pagination pageObj =
+            new CloudifyDeploymentList.Metadata.Pagination(1, 0, 1);
+        CloudifyDeploymentList.Metadata metadata = new CloudifyDeploymentList.Metadata(pageObj);
+
+        CloudifyDeploymentList cldDeployList = new CloudifyDeploymentList(cfyDeployItems, metadata);
+
+        ResponseEntity<CloudifyDeploymentList> response =
+            new ResponseEntity<CloudifyDeploymentList>(cldDeployList, HttpStatus.OK);
+
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<CloudifyDeploymentList>>any()))
+                .thenReturn(response);
+        
+        CloudifyDeploymentList actualResult = subject.getDeploymentInputs("id", "tenant");
         assertTrue(actualResult.items.get(0).id.equals("id"));
     }
+    
+
 }
+
index f90afa9..7d85196 100644 (file)
 package org.onap.ccsdk.dashboard.rest;
 
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import static org.mockito.Mockito.when;
 
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
-import org.json.JSONObject;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
 import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.onap.ccsdk.dashboard.model.ConsulDatacenter;
-import org.onap.ccsdk.dashboard.model.ConsulNodeInfo;
-import org.onap.ccsdk.dashboard.model.ConsulServiceHealth;
-import org.onap.ccsdk.dashboard.model.ConsulServiceInfo;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifySecret;
+import org.onap.ccsdk.dashboard.model.consul.ConsulDatacenter;
+import org.onap.ccsdk.dashboard.model.consul.ConsulDeploymentHealth;
+import org.onap.ccsdk.dashboard.model.consul.ConsulNodeInfo;
+import org.onap.ccsdk.dashboard.model.consul.ConsulServiceHealth;
+import org.onap.ccsdk.dashboard.model.consul.ConsulServiceInfo;
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
 import org.powermock.api.mockito.PowerMockito;
 import org.powermock.core.classloader.annotations.PrepareForTest;
@@ -64,36 +68,91 @@ public class ConsulRestClientImplTest {
 
     @Mock
     RestTemplate mockRest;
-
+    
     @InjectMocks
-    ConsulRestClientImpl subject = new ConsulRestClientImpl();
+    ConsulRestClientImpl subject;
+
+    String[] svcTags = {"cfytenantname=onap"}; 
+    
+    protected final static ObjectMapper objectMapper = new ObjectMapper();
+    static HttpClientErrorException httpException;
 
-    protected final ObjectMapper objectMapper = new ObjectMapper();
-    HttpClientErrorException httpException;
 
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception {
+        httpException = new HttpClientErrorException(HttpStatus.FORBIDDEN, "statusText");
+        objectMapper.registerModule(new Jdk8Module());    
+    }
+   
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        objectMapper.registerModule(new Jdk8Module());
-        httpException = new HttpClientErrorException(HttpStatus.BAD_REQUEST, "statusText");
         PowerMockito.mockStatic(DashboardProperties.class);
-        when(DashboardProperties.getControllerProperty("dev",
-            DashboardProperties.CONTROLLER_SUBKEY_CONSUL_URL)).thenReturn("https://invt.com");
-        this.subject.init();
+        when(DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_CONSUL_URL)).thenReturn("https://cnsl-svc.com");
+        when(DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_CLOUDIFY_URL)).thenReturn("https://orcl-svc.com");          
+        when(DashboardProperties.getControllerProperty("site.primary",
+                DashboardProperties.SITE_SUBKEY_CLOUDIFY_USERNAME)).thenReturn("admin");
+        when(DashboardProperties.getControllerProperty("site.primary",
+                DashboardProperties.SITE_SUBKEY_CLOUDIFY_PASS)).thenReturn("admin");
+        subject.setConsul_acl_token("consul_acl_token_for_dash");
+        subject.init();
     }
 
     @After
     public void tearDown() throws Exception {
     }
 
+    @Test
+    public final void testGetConsulAcl() {
+        String secretTokenStr =
+            "{\"created_at\": \"created_ts\", \"key\": \"acl_key\", \"updated_at\": \"updated_ts\", \"value\": \"acl_token_val\", \"visibility\": \"global\", \"is_hidden_value\": \"false\", \"tenant_name\": \"tenant\", \"resource_availability\": \"rsrc\"}";          
+        CloudifySecret sampleData = null;
+        try {
+            sampleData = objectMapper.readValue(secretTokenStr, CloudifySecret.class);
+        } catch (Exception e) {
+        }
+        
+        ResponseEntity<CloudifySecret> response =
+            new ResponseEntity<CloudifySecret>(sampleData, HttpStatus.OK);
+        
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<CloudifySecret>>any()))
+                .thenReturn(response);
+        String actualSecretStr = subject.getConsulAcl(mockRest);
+        assertTrue(actualSecretStr.equals("acl_token_val"));
+    }
+
+    @Test(expected = Exception.class)
+    public final void testCreateCfyRestTemplate() throws Exception {
+        String webapiUrl = DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_CLOUDIFY_URL);         
+        String user = DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_CLOUDIFY_USERNAME);
+        String pass = DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_CLOUDIFY_PASS);
+        URL url = null;
+        try {
+            url = new URL(webapiUrl);
+        } catch (MalformedURLException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        String urlScheme = webapiUrl.split(":")[0];
+        subject.createCfyRestTemplate(url, user, pass, urlScheme);
+    }
+    
     @Test
     public final void testGetServiceHealth() {
         ConsulServiceHealth consulSrvcHlth = new ConsulServiceHealth("cjlvmcnsl00",
             "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing",
             "This is a pgaas1_Service_ID health check",
-            "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n",
-            "pgaas1_Service_ID", "pgaasServer1", 190199, 199395);
+            "OK Output:",
+            "pgaas1_Service_ID", "pgaasServer1", svcTags, 34234, 4234);
 
+       // new ConsulServiceHealth()
         List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>();
         expectedCnslSrvcHlth.add(consulSrvcHlth);
 
@@ -109,21 +168,47 @@ public class ConsulRestClientImplTest {
         assertTrue(actualCnslSrvcHlth.get(0).node.equals("cjlvmcnsl00"));
     }
 
+    @Test(expected = Exception.class)
+    public final void get_svc_health_rest_client_exception() {
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<List<ConsulServiceHealth>>>any()))
+                .thenThrow(httpException);
+        
+        subject.getServiceHealth("dc1", "srvc1");      
+    }
+    
+    @Test(expected = Exception.class)
+    public final void get_services_rest_client_exception() {
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<Map<String, Object>>>any()))
+            .thenThrow(httpException);
+        subject.getServices("dc1");
+    }
+    
     @Test
-    @Ignore
     public final void testGetServices() {
         List<String> srvcIps = new ArrayList<String>();
         srvcIps.add("135.91.224.136");
         srvcIps.add("135.91.224.138");
         ConsulServiceInfo consulSrvcInfo = new ConsulServiceInfo("pgaasServer1", srvcIps);
 
+        Map<String, Object> respObj = new HashMap<String, Object>();
+        respObj.put("pgaasServer1", srvcIps);
+        
         List<ConsulServiceInfo> expectedCnslSrvcs = new ArrayList<ConsulServiceInfo>();
         expectedCnslSrvcs.add(consulSrvcInfo);
 
-        // ResponseEntity<Map<String, Object>> response = new ResponseEntity<Map<String,
-        // Object>>(consulSrvcInfo);
+        ResponseEntity<Map<String, Object>> response = 
+            new ResponseEntity<Map<String,Object>>(respObj, HttpStatus.OK);
+        
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<Map<String, Object>>>any())).thenReturn(response);
 
-        subject.getServices("dc1");
+        List<ConsulServiceInfo> actualSvcList = subject.getServices("dc1");
+        assertTrue(actualSvcList.get(0).name.equals("pgaasServer1"));
     }
 
     @Test
@@ -146,13 +231,22 @@ public class ConsulRestClientImplTest {
 
     }
 
+    @Test(expected = Exception.class)
+    public final void get_nodes_rest_client_exception() {
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<List<ConsulNodeInfo>>>any()))
+            .thenThrow(httpException);
+        subject.getNodes("dc1");
+    }
+     
     @Test
     public final void testGetNodeServicesHealth() {
         ConsulServiceHealth consulSrvcHlth = new ConsulServiceHealth("cjlvmcnsl00",
             "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing",
             "This is a pgaas1_Service_ID health check",
             "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n",
-            "pgaas1_Service_ID", "pgaasServer1", 190199, 199395);
+            "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395);
 
         List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>();
         expectedCnslSrvcHlth.add(consulSrvcHlth);
@@ -170,6 +264,15 @@ public class ConsulRestClientImplTest {
         assertTrue(actualNodeHlthList.get(0).node.equals("cjlvmcnsl00"));
     }
 
+    @Test(expected = Exception.class)
+    public final void get_node_svc_rest_client_exception() {
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<List<ConsulServiceHealth>>>any()))
+            .thenThrow(httpException);
+        subject.getNodeServicesHealth("dc1", "nodeId1");
+    }
+    
     @Test
     public final void testGetDatacenters() {
         ConsulDatacenter cnslDc = new ConsulDatacenter("dc1");
@@ -189,24 +292,45 @@ public class ConsulRestClientImplTest {
         assertTrue(actualDcList.get(0).name.equals("dc1"));
     }
 
-    @Test
-    @Ignore
-    public final void testRegisterService() {
-        fail("Not yet implemented"); // TODO
+    @Test(expected = Exception.class)
+    public final void get_dc_rest_client_exception() {
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<List<String>>>any()))
+            .thenThrow(httpException);
+        subject.getDatacenters();
     }
-
+    
     @Test
-    public final void testDeregisterService() {
+    public final void testGetServiceHealthByDeploymentId() {
+        ConsulServiceHealth consulSrvcHlth = new ConsulServiceHealth("cjlvmcnsl00",
+            "service:pgaas1_Service_ID", "Service 'pgaasServer1' check", "passing",
+            "This is a pgaas1_Service_ID health check",
+            "HTTP GET http://srvc.com:8000/healthcheck/status: 200 OK Output: { \"output\": \"Thu Apr 20 19:53:01 UTC 2017|INFO|masters=1 pgaas1.com|secondaries=0 |maintenance= |down=1 pgaas2.com| \" }\n",
+            "pgaas1_Service_ID", "pgaasServer1", svcTags, 190199, 199395);
 
-        JSONObject jsonResp = new JSONObject();
+        List<ConsulServiceHealth> expectedCnslSrvcHlth = new ArrayList<ConsulServiceHealth>();
+        expectedCnslSrvcHlth.add(consulSrvcHlth);
 
-        ResponseEntity<JSONObject> result = new ResponseEntity<JSONObject>(jsonResp, HttpStatus.OK);
-        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT),
-            Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<JSONObject>>any()))
-                .thenReturn(result);
+        ResponseEntity<List<ConsulServiceHealth>> response =
+            new ResponseEntity<List<ConsulServiceHealth>>(expectedCnslSrvcHlth, HttpStatus.OK);
 
-        int actualCode = subject.deregisterService("service1");
-        assertTrue(actualCode == 200);
-    }
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<List<ConsulServiceHealth>>>any()))
+                .thenReturn(response);
 
+        ConsulDeploymentHealth cdh = subject.getServiceHealthByDeploymentId("deploymentId");
+        assertTrue(cdh.getNode().equals("cjlvmcnsl00"));
+    }
+    
+    @Test(expected = Exception.class)
+    public final void get_svc_health_by_depId_rest_client_exception() {
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<List<ConsulServiceHealth>>>any()))
+            .thenThrow(httpException);
+        subject.getServiceHealthByDeploymentId("deploymentId");
+    }
+    
 }
index 7bd085b..2024d72 100644 (file)
@@ -36,17 +36,20 @@ import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
 import org.mockito.Matchers;
 import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 import org.onap.ccsdk.dashboard.exceptions.BadRequestException;
 import org.onap.ccsdk.dashboard.exceptions.DeploymentNotFoundException;
 import org.onap.ccsdk.dashboard.exceptions.DownstreamException;
 import org.onap.ccsdk.dashboard.exceptions.ServerErrorException;
 import org.onap.ccsdk.dashboard.exceptions.ServiceAlreadyExistsException;
+import org.onap.ccsdk.dashboard.model.cloudify.CloudifyDeployment;
 import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentLink;
 import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentRequest;
 import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponse;
 import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentResponseLinks;
 import org.onap.ccsdk.dashboard.model.deploymenthandler.DeploymentsListResponse;
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
+import org.onap.portalsdk.core.util.CacheManager;
 import org.powermock.api.mockito.PowerMockito;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
@@ -66,22 +69,42 @@ public class DeploymentHandlerClientImplTest {
     @Mock
     RestTemplate mockRest;
 
+    @Mock
+    CloudifyClient cfyClient;
+    
     @InjectMocks
     DeploymentHandlerClientImpl subject;
 
     @Before
     public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
         PowerMockito.mockStatic(DashboardProperties.class);
-        when(DashboardProperties.getControllerProperty("dev",
-            DashboardProperties.CONTROLLER_SUBKEY_DHANDLER_URL)).thenReturn("https://dplh.com");
+        when(DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_DHANDLER_URL)).thenReturn("https://dplh.com");
+        CacheManager testCache = new CacheManager();
+        subject.setCacheManager(testCache); 
         this.subject.init();
-
     }
 
     @After
     public void tearDown() throws Exception {
     }
 
+    @Test
+    public final void testCheckHealth() {
+        String expectStr = "DH mS health check";
+        ResponseEntity<String> response = 
+            new ResponseEntity<String>(expectStr, HttpStatus.OK);
+        
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<String>>any())).thenReturn(response)
+                .thenReturn(response);
+        
+        String actualStr = subject.checkHealth();
+        assertTrue(actualStr.equals(expectStr));
+    }
+
     @Test
     public final void testGetDeployments() {
         Collection<DeploymentLink> expectedDeplRefs = new ArrayList<DeploymentLink>();
@@ -205,93 +228,6 @@ public class DeploymentHandlerClientImplTest {
         subject.putDeployment("dpl12", "tenant12", deplReq);
     }
 
-    @Test
-    public final void testUpdateDeployment() throws Exception {
-        DeploymentRequest deplReq = new DeploymentRequest("serviceTypeId", null);
-
-        DeploymentResponseLinks newDeplItemLink =
-            new DeploymentResponseLinks("selfUrl", "statusUrl");
-        DeploymentResponse expectedDeplItem = new DeploymentResponse("req1", newDeplItemLink);
-
-        ResponseEntity<DeploymentResponse> response =
-            new ResponseEntity<DeploymentResponse>(expectedDeplItem, HttpStatus.OK);
-
-        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT),
-            Matchers.<HttpEntity<?>>any(),
-            Matchers.<ParameterizedTypeReference<DeploymentResponse>>any())).thenReturn(response);
-
-        DeploymentResponse actualResponse = subject.updateDeployment("dpl12", "tenant12", deplReq);
-        assertTrue(actualResponse.getRequestId().equals("req1"));
-    }
-
-    @Test(expected = DownstreamException.class)
-    public final void testUpdateDeployment_downstreamError() throws Exception {
-
-        DeploymentRequest deplReq = new DeploymentRequest("serviceTypeId", null);
-
-        HttpServerErrorException httpException =
-            new HttpServerErrorException(HttpStatus.BAD_GATEWAY, "statusText");
-
-        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT),
-            Matchers.<HttpEntity<?>>any(),
-            Matchers.<ParameterizedTypeReference<DeploymentResponse>>any()))
-                .thenThrow(httpException);
-
-        subject.updateDeployment("dpl12", "tenant12", deplReq);
-
-    }
-
-    @Test(expected = BadRequestException.class)
-    public final void testUpdateDeployment_badReqError() throws Exception {
-
-        DeploymentRequest deplReq = new DeploymentRequest("serviceTypeId", null);
-
-        HttpClientErrorException httpException =
-            new HttpClientErrorException(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "statusText");
-
-        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT),
-            Matchers.<HttpEntity<?>>any(),
-            Matchers.<ParameterizedTypeReference<DeploymentResponse>>any()))
-                .thenThrow(httpException);
-
-        subject.updateDeployment("dpl12", "tenant12", deplReq);
-
-    }
-
-    @Test(expected = ServiceAlreadyExistsException.class)
-    public final void testUpdateDeployment_srvcExistError() throws Exception {
-
-        DeploymentRequest deplReq = new DeploymentRequest("serviceTypeId", null);
-
-        HttpClientErrorException httpException =
-            new HttpClientErrorException(HttpStatus.CONFLICT, "statusText");
-
-        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT),
-            Matchers.<HttpEntity<?>>any(),
-            Matchers.<ParameterizedTypeReference<DeploymentResponse>>any()))
-                .thenThrow(httpException);
-
-        subject.updateDeployment("dpl12", "tenant12", deplReq);
-
-    }
-
-    @Test(expected = ServerErrorException.class)
-    public final void testUpdateDeployment_srvcError() throws Exception {
-
-        DeploymentRequest deplReq = new DeploymentRequest("serviceTypeId", null);
-
-        HttpServerErrorException httpException =
-            new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, "statusText");
-
-        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT),
-            Matchers.<HttpEntity<?>>any(),
-            Matchers.<ParameterizedTypeReference<DeploymentResponse>>any()))
-                .thenThrow(httpException);
-
-        subject.updateDeployment("dpl12", "tenant12", deplReq);
-
-    }
-
     @Test
     public final void testDeleteDeployment() throws Exception {
         DeploymentResponseLinks newDeplItemLink =
@@ -305,6 +241,12 @@ public class DeploymentHandlerClientImplTest {
             Matchers.<HttpEntity<?>>any(),
             Matchers.<ParameterizedTypeReference<DeploymentResponse>>any())).thenReturn(response);
 
+        CloudifyDeployment cfyDepl = 
+            new CloudifyDeployment("description", "blueprint_id", "created_at", "updated_at", 
+                "id", null, null, null, null, null, null, null, "tenant_name");
+
+        when(cfyClient.getDeploymentResource(Matchers.anyString(), Matchers.anyString())).thenReturn(cfyDepl);
+
         subject.deleteDeployment("deploymentId", "tenant");
     }
 
index d4c5e14..e0452d0 100644 (file)
@@ -30,6 +30,9 @@ import static org.mockito.Mockito.when;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Stream;
 
@@ -52,7 +55,11 @@ import org.onap.ccsdk.dashboard.model.inventory.ServiceType;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeList;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeQueryParams;
 import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeRequest;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeServiceMap;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummary;
+import org.onap.ccsdk.dashboard.model.inventory.ServiceTypeSummaryList;
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
+import org.onap.portalsdk.core.util.CacheManager;
 import org.powermock.api.mockito.PowerMockito;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
@@ -84,9 +91,13 @@ public class RestInventoryClientImplTest {
     ServiceList deplListNext = null;
     Service deplItem = null;
 
-    ServiceType bpItem = null;
-    ServiceTypeList bpList = null;
-    ServiceTypeList bpListNext = null;
+    ServiceTypeSummary bpItem, bpItem2 = null;
+    ServiceTypeSummaryList bpList, bpList2 = null;
+
+    ServiceType bpItemFull = null;
+    ServiceTypeList bpItemFullList = null;
+    
+    ServiceTypeSummaryList bpListNext = null;
 
     ServiceTypeRequest bpUploadItem = null;
 
@@ -94,11 +105,13 @@ public class RestInventoryClientImplTest {
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         objectMapper.registerModule(new Jdk8Module());
-        getExpectedBueprints();
+        getExpectedBlueprints();
         getExpectedDeployments();
         PowerMockito.mockStatic(DashboardProperties.class);
-        when(DashboardProperties.getControllerProperty("dev",
-            DashboardProperties.CONTROLLER_SUBKEY_INVENTORY_URL)).thenReturn("https://invt.com");
+        when(DashboardProperties.getControllerProperty("site.primary",
+            DashboardProperties.SITE_SUBKEY_INVENTORY_URL)).thenReturn("https://invt.com");
+        CacheManager testCache = new CacheManager();
+        subject.setCacheManager(testCache); 
         this.subject.init();
     }
 
@@ -122,96 +135,124 @@ public class RestInventoryClientImplTest {
         ServiceList.PaginationLinks paginationLinks2 =
             objectMapper.readValue(pageLinks2, ServiceList.PaginationLinks.class);
 
-        int totalCount = 2;
-        deplList = new ServiceList(items, totalCount, paginationLinks);
+        int totalCount = 1;
+        deplList = new ServiceList(items, totalCount, paginationLinks2);
         deplListNext = new ServiceList(items, totalCount, paginationLinks2);
     }
-
-    public void getExpectedBueprints()
+    
+    public void getExpectedBlueprints()
         throws JsonParseException, JsonMappingException, IOException {
-        bpItem = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906,
+        
+        bpItem = new ServiceTypeSummary.Builder().application("app1").component("comp1").
+        typeName("xyz1731-helm-1906").owner("xyz1731").typeVersion(1906).build();
+        
+        bpItem2 = new ServiceTypeSummary("xyz1731", "xyz1731-helm-1906", 1906, "app1", "comp1", "123-456-789",
+            "342343", true);
+        bpItemFull = new ServiceType.Builder("xyz1731", "xyz1731-helm-1906", 1906,
             "tosca_definitions_version: cloudify_dsl_1_3", "", "app1", "comp1").build();
-        Collection<ServiceType> items = new ArrayList<ServiceType>();
-        items.add(bpItem);
 
+        Collection<ServiceTypeSummary> items = new ArrayList<ServiceTypeSummary>();
+        items.add(bpItem);
+        Collection<ServiceTypeSummary> items2 = new ArrayList<ServiceTypeSummary>();
+        items2.add(bpItem2);        
+        
         String pageLinks =
-            "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-services/?offset=25\"}}";
+            "{\"previousLink\":null,\"nextLink\":{\"rel\":\"next\",\"href\":\"https://invt.com:30123/dcae-service-types/?offset=25\"}}";
         String pageLinks2 = "{\"previousLink\":null,\"nextLink\":null}";
-        ServiceTypeList.PaginationLinks paginationLinks =
-            objectMapper.readValue(pageLinks, ServiceTypeList.PaginationLinks.class);
-        ServiceTypeList.PaginationLinks paginationLinks2 =
-            objectMapper.readValue(pageLinks2, ServiceTypeList.PaginationLinks.class);
+        ServiceTypeSummaryList.PaginationLinks paginationLinks =
+            objectMapper.readValue(pageLinks, ServiceTypeSummaryList.PaginationLinks.class);
+        ServiceTypeSummaryList.PaginationLinks paginationLinks2 =
+            objectMapper.readValue(pageLinks2, ServiceTypeSummaryList.PaginationLinks.class);
 
         int totalCount = 2;
-        bpList = new ServiceTypeList(items, totalCount, paginationLinks);
-        bpListNext = new ServiceTypeList(items, totalCount, paginationLinks2);
+        bpList = new ServiceTypeSummaryList(items, totalCount, paginationLinks);
+        bpList2 = new ServiceTypeSummaryList(items2, totalCount, paginationLinks);
+        bpListNext = new ServiceTypeSummaryList(items, totalCount, paginationLinks2);
     }
 
     @Test
-    @Ignore
-    public final void testInit() {
-        fail("Not yet implemented"); // TODO
+    public final void testCheckHealth() {
+        String expectStr = "Inventory mS health check";
+        ResponseEntity<String> response = 
+            new ResponseEntity<String>(expectStr, HttpStatus.OK);
+        
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<String>>any())).thenReturn(response)
+                .thenReturn(response);
+        
+        String actualStr = subject.checkHealth();
+        assertTrue(actualStr.equals(expectStr));
     }
 
     @Test
     public final void testGetServiceTypes() {
-        /*
-         * String serviceTypeStr =
-         * "{\"paginationLinks\":{\"previousLink\":null,\"nextLink\":null}},\"totalCount\":32,\"items\":[{\"owner\":\"xyz1731\",\"typeName\":\"xyz1731-helm-1906\",\"typeVersion\":1906,\"blueprintTemplate\":\"tosca_definitions_version: cloudify_dsl_1_3\\nimports:\\n  - http://www.getcloudify.org/spec/cloudify/4.2/types.yaml\\n  - http://dockercentral.it.att.com:8093/nexus/repository/rawcentral/com.att.dcae.controller/type_files/helm/3.0.1/helm-type.yaml\\ninputs:\\n  deployment-description:\\n    default: ''\\n  chart-name:\\n    default: ''\\n  tiller-server:\\n    default: ''\\n  tiller-server-port:\\n    default: ''\\n  namespace:\\n    default: ''\\n  chart-repo-url:\\n    default: http://32.68.14.161/charts\\n  chart-version :\\n    default: ''\\n  config-url:\\n    default: ''\\n  config-format:\\n    default: ''\\n  tls-enable:\\n    description: enable helm TSL\\n    type: boolean\\n    default: false\\n  config-dir:\\n    description: config dir\\n    type: string\\n    default: '/opt/manager/resources/'\\n  stable-repo-url:\\n    description: URL for stable repository\\n    type: string\\n    default: 'http://32.68.14.161/stable'\\nnode_templates:\\n  ecompcomponent:\\n    type: onap.nodes.component\\n    properties:\\n      tiller-server-ip: { get_input: tiller-server }\\n      tiller-server-port: { get_input: tiller-server-port }\\n      component-name: { get_input: chart-name }\\n      chart-repo-url: { concat: [ 'http://', { get_secret: controller_helm_user }, ':', { get_secret: controller_helm_password }, '@', { get_input: chart-repo-url } ] }\\n      chart-version: { get_input: chart-version }\\n      namespace: { get_input: namespace }\\n      config-url:  { concat: [ 'http://', { get_secret: controller_helm_user }, ':', { get_secret: controller_helm_password }, '@', { get_input: config-url } ] }\\n      config-format: { get_input: config-format}\\n      tls-enable: { get_input: tls-enable}\\n      ca: { get_secret: ca_value}\\n      cert: { get_secret: cert_value}\\n      key: { get_secret: key_value}\\n      config-dir: { get_input: config-dir}\\n      stable-repo-url: { concat: [ 'http://', { get_secret: controller_helm_user }, ':', { get_secret: controller_helm_password }, '@', { get_input: stable-repo-url } ] }\\noutputs:\\n  ecompcomponent-helm-output:\\n    description: helm value and helm history\\n    value:\\n      helm-value: { get_attribute: [ecompcomponent, current-helm-value] }\\n      helm-history: { get_attribute: [ecompcomponent, helm-history] }\",\"serviceIds\":[],\"vnfTypes\":[],\"serviceLocations\":[],\"asdcServiceId\":\"\",\"asdcResourceId\":\"\",\"asdcServiceURL\":null,\"application\":\"ECOMP\",\"component\":\"controller\",\"typeId\":\"72b8577a-5043-43ab-9aa5-6808b8f53967\",\"selfLink\":{\"rel\":\"self\",\"href\":\"https://ecompc-invt-dev-s5.ecomp.idns.cip.att.com:30123/dcae-service-types/72b8577a-5043-43ab-9aa5-6808b8f53967\"},\"created\":1551214264536,\"deactivated\":null}]"
-         * ; ServiceTypeList sampleData = null; try { sampleData =
-         * objectMapper.readValue(serviceTypeStr, ServiceTypeList.class); } catch
-         * (Exception e) { }
-         */
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> expectedResult = items.stream();
-
-        ResponseEntity<ServiceTypeList> response =
-            new ResponseEntity<ServiceTypeList>(bpList, HttpStatus.OK);
-
-        ResponseEntity<ServiceTypeList> response2 =
-            new ResponseEntity<ServiceTypeList>(bpListNext, HttpStatus.OK);
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> expectedResult = items.stream();
+
+        ResponseEntity<ServiceTypeSummaryList> response =
+            new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK);
+
+        ResponseEntity<ServiceTypeSummaryList> response2 =
+            new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK);
 
         when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
             Matchers.<HttpEntity<?>>any(),
-            Matchers.<ParameterizedTypeReference<ServiceTypeList>>any())).thenReturn(response)
+            Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response)
                 .thenReturn(response2);
 
-        Stream<ServiceType> actualResult = subject.getServiceTypes();
+        Stream<ServiceTypeSummary> actualResult = subject.getServiceTypes();
         assertNotNull(actualResult);
         assertTrue(expectedResult.count() == actualResult.count());
     }
 
+    @Test
+    public final void testCacheServiceTypes() {
+        ResponseEntity<ServiceTypeSummaryList> response =
+            new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK);
+
+        ResponseEntity<ServiceTypeSummaryList> response2 =
+            new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK);
+
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response)
+                .thenReturn(response2);
+        
+        subject.cacheServiceTypes();
+    }
+    
     @Test
     public final void testGetServiceTypesServiceTypeQueryParams() {
         ServiceTypeQueryParams qryParms = new ServiceTypeQueryParams.Builder()
             .asdcResourceId("asdcResourceId").asdcServiceId("asdcServiceId").onlyActive(true)
             .onlyLatest(false).serviceId("serviceId").serviceLocation("serviceLocation")
             .typeName("typeName").vnfType("vnfType").build();
-        Collection<ServiceType> items = bpList.items;
-        Stream<ServiceType> expectedResult = items.stream();
+        Collection<ServiceTypeSummary> items = bpList.items;
+        Stream<ServiceTypeSummary> expectedResult = items.stream();
 
-        ResponseEntity<ServiceTypeList> response =
-            new ResponseEntity<ServiceTypeList>(bpList, HttpStatus.OK);
+        ResponseEntity<ServiceTypeSummaryList> response =
+            new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK);
 
-        ResponseEntity<ServiceTypeList> response2 =
-            new ResponseEntity<ServiceTypeList>(bpListNext, HttpStatus.OK);
+        ResponseEntity<ServiceTypeSummaryList> response2 =
+            new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK);
 
         when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
             Matchers.<HttpEntity<?>>any(),
-            Matchers.<ParameterizedTypeReference<ServiceTypeList>>any())).thenReturn(response)
+            Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response)
                 .thenReturn(response2);
 
-        Stream<ServiceType> actualResult = subject.getServiceTypes(qryParms);
+        Stream<ServiceTypeSummary> actualResult = subject.getServiceTypes(qryParms);
         assertNotNull(actualResult);
         assertTrue(expectedResult.count() == actualResult.count());
     }
 
     @Test
     public final void testGetServiceType() {
-        Optional<ServiceType> expectedResult = Optional.of(bpItem);
+        Optional<ServiceType> expectedResult = Optional.of(bpItemFull);
 
         ResponseEntity<ServiceType> response =
-            new ResponseEntity<ServiceType>(bpItem, HttpStatus.OK);
+            new ResponseEntity<ServiceType>(bpItemFull, HttpStatus.OK);
 
         when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
             Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<ServiceType>>any()))
@@ -222,140 +263,87 @@ public class RestInventoryClientImplTest {
     }
 
     @Test
-    public final void testAddServiceTypeServiceType() {
-
-        when(mockRest.postForObject(Matchers.anyString(), Matchers.<HttpEntity<?>>any(),
-            Matchers.<Class<ServiceType>>any())).thenReturn(bpItem);
-
-        ServiceType actualResult = subject.addServiceType(bpItem);
-        assertTrue(actualResult.getTypeName().contains("xyz"));
-    }
-
-    @Test
-    public final void testAddServiceTypeServiceTypeRequest() {
-        ServiceTypeRequest srvcReq = ServiceTypeRequest.from(bpItem);
-
-        when(mockRest.postForObject(Matchers.anyString(), Matchers.<HttpEntity<?>>any(),
-            Matchers.<Class<ServiceType>>any())).thenReturn(bpItem);
-
-        ServiceType actualResult = subject.addServiceType(srvcReq);
-        assertTrue(actualResult.getTypeName().contains("xyz"));
-    }
-
-    @Test
-    public final void testDeleteServiceType() throws Exception {
-        ResponseEntity<ApiResponseMessage> response =
-            new ResponseEntity<ApiResponseMessage>(HttpStatus.OK);
-
-        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.DELETE),
-            Matchers.<HttpEntity<?>>any(),
-            Matchers.<ParameterizedTypeReference<ApiResponseMessage>>any())).thenReturn(response);
-
-        subject.deleteServiceType("4243234");
-    }
-
-    @Test
-    public final void testGetServices() {
-
-        Collection<Service> items = deplList.items;
-        Stream<Service> expectedResult = items.stream();
-
+    public final void testGetServicesForType() throws Exception {
+        String typeId = "44234234";
+        ServiceRef expectedSrvc = new ServiceRef("dcae_dtiapi_1902", "432423", "433434");
+        Collection<ServiceRef> expectedSrvcIds = new ArrayList<ServiceRef>();
+        expectedSrvcIds.add(expectedSrvc);
+        ServiceRefList expectedSvcRefList = new ServiceRefList(expectedSrvcIds, 1);
         ResponseEntity<ServiceList> response =
             new ResponseEntity<ServiceList>(deplList, HttpStatus.OK);
 
-        ResponseEntity<ServiceList> response2 =
-            new ResponseEntity<ServiceList>(deplListNext, HttpStatus.OK);
-
         when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
             Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<ServiceList>>any()))
-                .thenReturn(response).thenReturn(response2);
-
-        Stream<Service> actualResult = subject.getServices();
-        assertNotNull(actualResult);
-        assertTrue(expectedResult.count() == actualResult.count());
-
-    }
-
-    @Test
-    public final void testGetServicesForType() {
-        ResponseEntity<ServiceList> response =
-            new ResponseEntity<ServiceList>(deplList, HttpStatus.OK);
-
-        ResponseEntity<ServiceList> response2 =
-            new ResponseEntity<ServiceList>(deplListNext, HttpStatus.OK);
-
-        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
-            Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<ServiceList>>any()))
-                .thenReturn(response).thenReturn(response2);
-        ServiceQueryParams qryParms = new ServiceQueryParams.Builder().typeId("typeId").build();
-
-        ServiceRefList actualResult = subject.getServicesForType(qryParms);
-        assertTrue(actualResult.items.size() == 2);
-        ServiceRef actualSrvcItem = (ServiceRef) actualResult.items.toArray()[0];
-        assertTrue(actualSrvcItem.getServiceId().contains("dtiapi"));
-
+                .thenReturn(response);
+        
+        ServiceQueryParams qryParams = new ServiceQueryParams.Builder().typeId(typeId).build();
+        ServiceRefList actualSvcRefList = subject.getServicesForType(qryParams);
+        assertTrue(actualSvcRefList.totalCount == expectedSvcRefList.totalCount);  
     }
-
+    
     @Test
-    public final void testGetServicesServiceQueryParams() {
-        ServiceQueryParams qryParms = new ServiceQueryParams.Builder().typeId("typeId")
-            .vnfId("vnfId").vnfLocation("vnfLocation").vnfType("vnfType")
-            .componentType("componentType").shareable(false).created("43443423").build();
-
-        Collection<Service> items = deplList.items;
-        Stream<Service> expectedResult = items.stream();
-
-        ResponseEntity<ServiceList> response =
-            new ResponseEntity<ServiceList>(deplList, HttpStatus.OK);
-
-        ResponseEntity<ServiceList> response2 =
-            new ResponseEntity<ServiceList>(deplListNext, HttpStatus.OK);
-
-        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
-            Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<ServiceList>>any()))
-                .thenReturn(response).thenReturn(response2);
+    public final void testAddServiceTypeServiceType() {
 
-        Stream<Service> actualResult = subject.getServices(qryParms);
-        assertTrue(expectedResult.count() == actualResult.count());
-    }
+        when(mockRest.postForObject(Matchers.anyString(), Matchers.<HttpEntity<?>>any(),
+            Matchers.<Class<ServiceType>>any())).thenReturn(bpItemFull);
 
-    @Test
-    public final void testGetService() {
-        Optional<Service> expectedResult = Optional.of(deplItem);
+        ResponseEntity<ServiceTypeSummaryList> response =
+            new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK);
 
-        ResponseEntity<Service> response = new ResponseEntity<Service>(deplItem, HttpStatus.OK);
+        ResponseEntity<ServiceTypeSummaryList> response2 =
+            new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK);
 
         when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
-            Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<Service>>any()))
-                .thenReturn(response);
-
-        Optional<Service> actualResult = subject.getService("432432423");
-        assertTrue(
-            expectedResult.get().getDeploymentRef().equals(actualResult.get().getDeploymentRef()));
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response)
+                .thenReturn(response2);
+        
+        ServiceType actualResult = subject.addServiceType(bpItemFull);
+        assertTrue(actualResult.getTypeName().contains("xyz"));
     }
 
     @Test
-    public final void testPutService() {
+    public final void testAddServiceTypeServiceTypeRequest() {
+        ServiceTypeRequest srvcReq = ServiceTypeRequest.from(bpItemFull);
 
-        ResponseEntity<Service> response = new ResponseEntity<Service>(deplItem, HttpStatus.OK);
+        when(mockRest.postForObject(Matchers.anyString(), Matchers.<HttpEntity<?>>any(),
+            Matchers.<Class<ServiceType>>any())).thenReturn(bpItemFull);
+        
+        ResponseEntity<ServiceTypeSummaryList> response =
+            new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK);
 
-        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.PUT),
-            Matchers.<HttpEntity<?>>any(), Matchers.<ParameterizedTypeReference<Service>>any()))
-                .thenReturn(response);
+        ResponseEntity<ServiceTypeSummaryList> response2 =
+            new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK);
 
-        subject.putService("423423", deplItem);
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response)
+                .thenReturn(response2);
+        ServiceType actualResult = subject.addServiceType(srvcReq);
+        assertTrue(actualResult.getTypeName().contains("xyz"));
     }
 
     @Test
-    public final void testDeleteService() throws Exception {
+    public final void testDeleteServiceType() throws Exception {
         ResponseEntity<ApiResponseMessage> response =
             new ResponseEntity<ApiResponseMessage>(HttpStatus.OK);
 
         when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.DELETE),
             Matchers.<HttpEntity<?>>any(),
             Matchers.<ParameterizedTypeReference<ApiResponseMessage>>any())).thenReturn(response);
+        
+        ResponseEntity<ServiceTypeSummaryList> response1 =
+            new ResponseEntity<ServiceTypeSummaryList>(bpList, HttpStatus.OK);
+
+        ResponseEntity<ServiceTypeSummaryList> response2 =
+            new ResponseEntity<ServiceTypeSummaryList>(bpListNext, HttpStatus.OK);
 
-        subject.deleteService("4243234");
+        when(mockRest.exchange(Matchers.anyString(), Matchers.eq(HttpMethod.GET),
+            Matchers.<HttpEntity<?>>any(),
+            Matchers.<ParameterizedTypeReference<ServiceTypeSummaryList>>any())).thenReturn(response1)
+                .thenReturn(response2);
+        
+        subject.deleteServiceType("4243234");
     }
 
 }
index 9c89ffd..837c813 100644 (file)
@@ -1144,4 +1144,7 @@ INSERT INTO dashboard_pg_db_common.fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDE
 Insert into dashboard_pg_db_common.fn_role_function (ROLE_ID,FUNCTION_CD) values (1,'menu_api');
 Insert into dashboard_pg_db_common.fn_role_function (ROLE_ID,FUNCTION_CD) values (2,'menu_api');
 Insert into dashboard_pg_db_common.fn_role_function (ROLE_ID,FUNCTION_CD) values (3,'menu_api');
-Insert into dashboard_pg_db_common.fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_api');
\ No newline at end of file
+Insert into dashboard_pg_db_common.fn_role_function (ROLE_ID,FUNCTION_CD) values (16,'menu_api');
+
+INSERT INTO dashboard_pg_db_common.fn_menu (MENU_ID, LABEL, PARENT_ID, SORT_ORDER, ACTION, FUNCTION_CD, ACTIVE_YN, SERVLET, QUERY_STRING, EXTERNAL_URL, TARGET, MENU_SET_CD, SEPARATOR_YN, IMAGE_SRC)
+       VALUES (30015,'Cloudify Plugins', 30011,     50,'ecd#/iplug',      'menu_inventory',           'Y','N/A','N/A','N/A','N/A','APP','N',NULL);
\ No newline at end of file
index 7b71941..8c8b017 100644 (file)
@@ -6,12 +6,12 @@
        <parent>
                <groupId>org.onap.ccsdk.dashboard</groupId>
                <artifactId>ccsdk-app-parent</artifactId>
-               <version>1.3.2-SNAPSHOT</version>
+               <version>1.4.0-SNAPSHOT</version>
        </parent>
 
        <groupId>org.onap.ccsdk.dashboard</groupId>
        <artifactId>ccsdk-app-os</artifactId>
-       <version>1.3.2-SNAPSHOT</version>
+       <version>1.4.0-SNAPSHOT</version>
        <packaging>war</packaging>
        <name>ONAP Operations Manager Dashboard app</name>
        <description>CCSDK Dashboard Web Application for external release</description>
@@ -68,7 +68,7 @@
                <finalName>${project.artifactId}-${build.version}</finalName>
 
                <plugins>
-                       <!-- Compile to Java 1.8 class output format -->
+                       <!-- Compile to Java 1.8 class output format --> 
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-compiler-plugin</artifactId>
                                                <overlay>
                                                        <groupId>org.onap.ccsdk.dashboard</groupId>
                                                        <artifactId>ccsdk-app-overlay</artifactId>
+                                                       <excludes>
+                                                               <exclude>app/ccsdk/home/api_view.html</exclude>
+                                                               <exclude>app/ccsdk/home/ecd_router.js</exclude>
+                                                               <exclude>app/ccsdk/home/executions_view.html</exclude>
+                                                               <exclude>app/ccsdk/home/executions-view-controller.js</exclude>
+                                                               <exclude>app/ccsdk/home/ecd_spa.html</exclude>
+                                                               <exclude>app/ccsdk/home/ecd-style.css</exclude>
+                                                       </excludes>
                                                </overlay>
                                                <overlay>
                                                        <groupId>org.onap.portal.sdk</groupId>
index 807ae78..665e0da 100644 (file)
@@ -21,18 +21,16 @@ package org.onap.portalapp.conf;
 
 import java.util.ArrayList;
 import java.util.List;
-
-import org.onap.portalapp.lm.FusionLicenseManagerImpl;
 import org.onap.portalapp.login.LoginStrategyImpl;
 import org.onap.portalapp.controller.core.SingleSignOnController;
 import org.onap.portalapp.controller.sample.ElasticSearchController;
 import org.onap.portalapp.controller.sample.PostDroolsController;
+import org.onap.portalapp.interceptor.AuthenticationInterceptor;
+import org.onap.portalapp.interceptor.AuthorizationInterceptor;
 import org.onap.portalapp.scheduler.LogRegistry;
 import org.onap.portalsdk.core.auth.LoginStrategy;
 import org.onap.portalsdk.core.conf.AppConfig;
 import org.onap.portalsdk.core.conf.Configurable;
-// import org.onap.portalsdk.core.lm.FusionLicenseManager;
-// import org.onap.portalsdk.core.lm.FusionLicenseManagerUtils;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
 import org.onap.portalsdk.core.objectcache.AbstractCacheManager;
 import org.onap.portalsdk.core.scheduler.CoreRegister;
@@ -54,6 +52,7 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 
+
 /**
  * ECOMP Portal SDK sample application. ECOMP Portal SDK core AppConfig class to
  * reuse interceptors, view resolvers and other features defined there.
@@ -75,6 +74,8 @@ public class ExternalAppConfig extends AppConfig implements Configurable {
 
     private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ExternalAppConfig.class);
 
+    private static final String HEALTH = "/health*";
+    
     @Configuration
     @Import(SystemProperties.class)
     static class InnerConfiguration {
@@ -133,6 +134,16 @@ public class ExternalAppConfig extends AppConfig implements Configurable {
         return definitions;
     }
 
+    @Bean
+    public AuthenticationInterceptor authenticationInterceptor() {
+         return new AuthenticationInterceptor();
+     }
+    
+    @Bean
+    public AuthorizationInterceptor authorizationInterceptor() {
+         return new AuthorizationInterceptor();
+     }
+    
     /**
      * Adds request interceptors to the specified registry by calling
      * {@link AppConfig#addInterceptors(InterceptorRegistry)}, but excludes
@@ -140,6 +151,8 @@ public class ExternalAppConfig extends AppConfig implements Configurable {
      */
     @Override
     public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/nb-api/**");
+        registry.addInterceptor(authorizationInterceptor()).addPathPatterns("/nb-api/**");
         super.setExcludeUrlPathsForSessionTimeout("/login_external", "*/login_external.htm",
             "login", "/login.htm", "/api*", "/single_signon.htm", "/single_signon", "/health*",
             "/nb-api/**");
@@ -171,4 +184,5 @@ public class ExternalAppConfig extends AppConfig implements Configurable {
     public LoginStrategy loginStrategy() {
         return new LoginStrategyImpl();
     }
+
 }
index 9c6b95e..2624e2f 100644 (file)
  */
 package org.onap.portalapp.conf;
 
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
 import org.onap.ccsdk.dashboard.util.DashboardProperties;
 import org.onap.portalsdk.core.conf.AppInitializer;
+import org.onap.portalsdk.core.logging.format.AlarmSeverityEnum;
+import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.web.context.WebApplicationContext;
 
 public class ExternalAppInitializer extends AppInitializer {
 
+    /*
+    @Override
+    protected WebApplicationContext createServletApplicationContext() {
+        WebApplicationContext context = super.createServletApplicationContext();
+        try {
+            ((ConfigurableEnvironment) context.getEnvironment()).setActiveProfiles("onap");
+        } catch (Exception e) {
+            System.out.println("Unable to set the active profile" + e.getMessage());
+            //throw e;
+        }
+        return context;
+    }
+*/
     @Override
     protected Class<?>[] getRootConfigClasses() {
         return super.getRootConfigClasses();
index 673fc8d..844ae36 100644 (file)
@@ -43,8 +43,8 @@ public class HibernateMappingLocations implements HibernateMappingLocatable {
             // a leading slash gets stripped so don't bother.
             // new ClassPathResource("../fusion/orm/Fusion.hbm.xml"),
             // This is a COPY to work around a bug in the 1.1.0 release.
-            new ClassPathResource("../fusion/orm/Fusion.hbm.xml"),
-            new ClassPathResource("../oom-app.hbm.xml")};
+            new ClassPathResource("../fusion/orm/Fusion.hbm.xml")};
+            //new ClassPathResource("../oom-app.hbm.xml")};
     }
 
     /*
diff --git a/ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthenticationInterceptor.java b/ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthenticationInterceptor.java
new file mode 100644 (file)
index 0000000..206f364
--- /dev/null
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.portalapp.interceptor;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+//import javax.xml.bind.DatatypeConverter;
+import java.util.Base64;
+
+import org.apache.http.HttpStatus;
+import org.onap.portalsdk.core.domain.User;
+import org.onap.portalsdk.core.service.UserProfileService;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+public class AuthenticationInterceptor implements HandlerInterceptor {
+
+       @Autowired
+       private UserProfileService userSvc;
+       
+       @Override
+       public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
+               String authString = request.getHeader("Authorization");
+               try {
+               if(authString == null || authString.isEmpty())
+               {
+                       response.setStatus(HttpStatus.SC_UNAUTHORIZED);
+                       response.sendError(HttpStatus.SC_UNAUTHORIZED, "Authentication information is missing");
+                       return false; //Do not continue with request
+               } else {
+                       String decodedAuth = "";
+                       String[] authParts = authString.split("\\s+");
+                       String authInfo = authParts[1];
+                       byte[] bytes = null;
+                       bytes = Base64.getDecoder().decode(authInfo);
+                                       //DatatypeConverter.parseBase64Binary(authInfo);
+                       decodedAuth = new String(bytes,StandardCharsets.UTF_8);
+                       String[] authen = decodedAuth.split(":");
+
+                       if  (authen.length > 1) {
+                           User user = userSvc.getUserByLoginId(authen[0]);
+                           if (user == null) {
+                        response.sendError(HttpStatus.SC_UNAUTHORIZED, "Un-authorized to perform this operation");
+                           return false;
+                           }
+/*                             ResponseEntity<String> getResponse = 
+                                   userSrvc.checkUserExists(authen[0], authen[1]);
+                               if (getResponse.getStatusCode().value() != 200) {       
+                                       response.sendError(HttpStatus.SC_UNAUTHORIZED, "Un-authorized to perform this operation");
+                                       return false;
+                               }*/
+                       } else {
+                               return false;
+                       }
+               }
+               } catch (Exception e) {
+                       try {
+                               response.sendError(HttpStatus.SC_UNAUTHORIZED, e.getMessage());
+                       } catch (IOException e1) {
+                               return false;
+                       }
+                       return false;
+               }
+               return true; //Continue with request
+       }
+       
+       @Override
+       public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
+                       ModelAndView modelAndView) throws Exception {
+               //Ignore
+       }
+       
+       @Override
+       public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
+                       throws Exception {
+               //Ignore
+       }
+}
diff --git a/ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthorizationInterceptor.java b/ccsdk-app-os/src/main/java/org/onap/portalapp/interceptor/AuthorizationInterceptor.java
new file mode 100644 (file)
index 0000000..2f3362b
--- /dev/null
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ * Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+package org.onap.portalapp.interceptor;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class AuthorizationInterceptor implements HandlerInterceptor {
+    
+    protected final ObjectMapper objectMapper = new ObjectMapper();
+    
+       @Override
+       public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        Set<String> userRoleSet = new HashSet<String>();
+        Set<String> userApps = new TreeSet<>();
+        userRoleSet.add("Standard User");
+        userRoleSet.add("ECOMPC_DCAE_WRITE");
+        userApps.add("dcae");
+        request.setAttribute("userRoles", userRoleSet);
+        request.setAttribute("userApps", userApps);       
+               return true; //Continue with request
+       }
+       
+       @Override
+       public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
+                       ModelAndView modelAndView) throws Exception {
+               //Ignore
+       }
+       
+       @Override
+       public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
+                       throws Exception {
+               //Ignore
+       }
+}
index b628772..d7c9ab7 100644 (file)
 
 package org.onap.portalapp.login;
 
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Predicate;
+
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.onap.portalsdk.core.auth.LoginStrategy;
+import org.onap.portalsdk.core.command.LoginBean;
+import org.onap.portalsdk.core.domain.Role;
+import org.onap.portalsdk.core.domain.RoleFunction;
+import org.onap.portalsdk.core.domain.User;
+import org.onap.portalsdk.core.domain.FusionObject.Parameters;
 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.onap.portalsdk.core.menu.MenuProperties;
 import org.onap.portalsdk.core.onboarding.exception.PortalAPIException;
 import org.onap.portalsdk.core.onboarding.util.CipherUtil;
 import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
 import org.onap.portalsdk.core.onboarding.util.PortalApiProperties;
+import org.onap.portalsdk.core.service.DataAccessService;
+import org.onap.portalsdk.core.service.LoginService;
+import org.onap.portalsdk.core.service.RoleService;
+import org.onap.portalsdk.core.util.SystemProperties;
+import org.onap.portalsdk.core.web.support.AppUtils;
+import org.onap.portalsdk.core.web.support.UserUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.servlet.ModelAndView;
 
 public class LoginStrategyImpl extends LoginStrategy {
 
     EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(LoginStrategyImpl.class);
 
+    @Autowired
+    private LoginService loginService;
+
+    @Autowired
+    private RoleService roleService;
+       
+    @Override
+    public ModelAndView doExternalLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
+
+        invalidateExistingSession(request);
+
+        LoginBean commandBean = new LoginBean();
+        String loginId = request.getParameter("loginId");
+        String password = request.getParameter("password");
+        commandBean.setLoginId(loginId);
+        commandBean.setLoginPwd(password);
+        //commandBean.setUserid(loginId);
+        commandBean = loginService.findUser(commandBean,
+                (String) request.getAttribute(MenuProperties.MENU_PROPERTIES_FILENAME_KEY), new HashMap());
+        List<RoleFunction> roleFunctionList = roleService.getRoleFunctions(loginId);
+
+        if (commandBean.getUser() == null) {
+            String loginErrorMessage = (commandBean.getLoginErrorMessage() != null) ? commandBean.getLoginErrorMessage()
+                    : "login.error.external.invalid - User name and/or password incorrect";
+            Map<String, String> model = new HashMap<>();
+            model.put("error", loginErrorMessage);
+            return new ModelAndView("login_external", "model", model);
+        } else {
+            // store the currently logged in user's information in the session
+            UserUtils.setUserSession(request, commandBean.getUser(), commandBean.getMenu(),
+                    commandBean.getBusinessDirectMenu(),
+                    SystemProperties.getProperty(SystemProperties.LOGIN_METHOD_BACKDOOR), roleFunctionList);
+            // set the user's max role level in session
+            final String adminRole = "System Administrator";
+            final String standardRole = "Standard User";
+            final String readRole = "Read Access";
+            final String writeRole = "Write Access";
+            
+            String maxRole = "";
+            String authType = "READ";
+            String accessLevel = "app";
+            
+            Predicate<Role> adminRoleFilter = 
+                p -> p.getName() != null && p.getName().equalsIgnoreCase(adminRole);
+            
+            Predicate<Role> writeRoleFilter = 
+                p -> p.getName() != null && (p.getName().equalsIgnoreCase(writeRole) || p.getName().equalsIgnoreCase(standardRole));
+            
+            Predicate<Role> readRoleFilter = 
+                p -> p.getName() != null && (p.getName().equalsIgnoreCase(readRole) );               
+
+            if (UserUtils.getUserSession(request) != null) {
+                @SuppressWarnings("unchecked")
+                Collection<org.onap.portalsdk.core.domain.Role> userRoles = 
+                    UserUtils.getRoles(request).values();
+                if (userRoles.stream().anyMatch(adminRoleFilter) ) {
+                    maxRole = "admin";
+                } else if (userRoles.stream().anyMatch(writeRoleFilter) ) {
+                    maxRole = "write";
+                } else if (userRoles.stream().anyMatch(readRoleFilter) ) {
+                    maxRole = "read";
+                }
+                switch(maxRole) {
+                    case "admin":
+                        authType = "ADMIN";
+                        accessLevel = "ops";
+                        break;
+                    case "write":
+                        authType = "WRITE";
+                        accessLevel = "dev";                
+                        break;
+                    case "read":
+                        authType = "READ";
+                        accessLevel = "dev";                
+                        break;              
+                    default:
+                        accessLevel = "app";                
+                }
+            }
+            AppUtils.getSession(request).setAttribute("role_level", accessLevel);
+            AppUtils.getSession(request).setAttribute("auth_role", authType);
+            initateSessionMgtHandler(request);
+            // user has been authenticated, now take them to the welcome page
+            return new ModelAndView("redirect:welcome");
+        }
+    }
+    
     @Override
     public ModelAndView doLogin(HttpServletRequest request, HttpServletResponse response)
         throws Exception {
index 88ef37c..1ab01ef 100644 (file)
@@ -27,6 +27,9 @@ portal.api.prefix = /api
 max.idle.time = 5\r
 user.attribute.name = user_attribute\r
 \r
+# CSP Global Log On for single sign on\r
+ecomp_redirect_url = https://webtest.csp.att.com/ecompportal/\r
+\r
 # URL of the ECOMP Portal REST API\r
 ecomp_rest_url = http://portal.api.simpledemo.openecomp.org/ecompportal/auxapi\r
 \r
index 9335e72..7a02e5a 100644 (file)
@@ -2,14 +2,14 @@
   "swagger": "2.0",
   "info": {
     "description": "API to manage deployment of microservices using blueprints.",
-    "version": "1.3.0",
+    "version": "1.4.0",
     "title": "DCAE Dashboard API",
     "contact": {
       "email": "rp5662@att.com"
     }
   },
   "host": "dcae-dashboard:8080",
-  "basePath": "/ccsdk-app/nb-api",
+  "basePath": "/ccsdk-app/nb-api/v2",
   "tags": [
     {
       "name": "Blueprints",
     {
       "name": "Tenants",
       "description": "Query Cloudify Tenants"
-    },
-    {
-      "name": "Components",
-      "description": "Query on-boarded components"
     }
   ],
   "schemes": [
         }
       }
     },
-    "/components": {
-      "get": {
-        "tags": [
-          "Components"
-        ],
-        "summary": "Lists all application components",
-        "description": "Query all components from database",
-        "operationId": "List Components",
-        "produces": [
-          "application/json"
-        ],
-        "parameters": [],
-        "responses": {
-          "200": {
-            "description": "successful operation",
-            "schema": {
-              "type": "array",
-              "items": {
-                "$ref": "#/definitions/Component"
-              }
-            }
-          },
-          "400": {
-            "description": "Invalid status value"
-          }
-        }
-      },
-      "post": {
-        "tags": [
-          "Components"
-        ],
-        "summary": "add an application component",
-        "description": "Insert a component into database",
-        "operationId": "Add Component",
-        "consumes": [
-          "application/json"
-        ],
-        "parameters": [
-          {
-            "in": "body",
-            "name": "body",
-            "description": "New component input",
-            "required": true,
-            "schema": {
-              "$ref": "#/definitions/ComponentInput"
-            }
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "successful operation",
-            "schema": {
-              "type": "object"
-            }
-          },
-          "400": {
-            "description": "Invalid status value"
-          }
-        }
-      }
-    },
     "/deployments": {
       "get": {
         "tags": [
           "Deployments"
         ],
-        "summary": "Lists all Deployments",
+        "summary": "List all Deployments",
         "description": "Query all deployments or Service objects from Inventory",
         "operationId": "List Deployments",
         "produces": [
         "tags": [
           "Deployments"
         ],
-        "summary": "Gets a Deployment",
+        "summary": "Get a Deployment",
         "description": "Query a deployment or Service object from Inventory",
         "operationId": "Get Deployment",
         "produces": [
         }
       }
     },
-    "/deployments/{deploymentId}/update": {
-      "put": {
-        "tags": [
-          "Deployments"
-        ],
-        "summary": "Update an existing deployment",
-        "description": "Dispatch a request to Deployment handler mS to use Cloudify deployment update operation ",
-        "operationId": "Update Deployment",
-        "consumes": [
-          "application/json"
-        ],
-        "produces": [
-          "application/json"
-        ],
-        "parameters": [
-          {
-            "name": "deploymentId",
-            "in": "path",
-            "description": "ID of deployment to update",
-            "required": true,
-            "type": "string"
-          },
-          {
-            "in": "body",
-            "name": "body",
-            "description": "Inputs to initiate a deployment: blueprint ID from inventory, Cloudify tenant name, blueprint inputs",
-            "required": true,
-            "schema": {
-              "$ref": "#/definitions/DeploymentInput"
-            }
-          }
-        ],
-        "responses": {
-          "400": {
-            "description": "Invalid ID supplied"
-          },
-          "404": {
-            "description": "Deployment not found"
-          },
-          "405": {
-            "description": "Validation exception"
-          }
-        }
-      }
-    },
     "/deployments/{deploymentId}/executions": {
       "get": {
         "tags": [
           }
         }
       }
-    },
-    "/blueprints/findByName": {
-      "get": {
-        "tags": [
-          "Blueprints"
-        ],
-        "summary": "Find a blueprint by a name pattern",
-        "description": "Fetch the blueprint objects from inventory whose names match a string pattern",
-        "operationId": "Get Blueprint",
-        "produces": [
-          "application/json"
-        ],
-        "parameters": [
-          {
-            "name": "name",
-            "in": "query",
-            "description": "name pattern to filter by",
-            "required": true,
-            "type": "string"
-          },
-          {
-            "name": "_include",
-            "in": "query",
-            "description": "blueprint object properties need to be considered for filter",
-            "required": false,
-            "type": "array",
-            "items": {
-              "type": "string",
-              "enum": [
-                "typeName",
-                "typeId",
-                "typeVersion"
-              ],
-              "default": "typeName"
-            },
-            "collectionFormat": "multi"
-          }
-        ],
-        "responses": {
-          "200": {
-            "description": "List of `DCAEServiceType` objects",
-            "schema": {
-              "$ref": "#/definitions/InlineResponse200"
-            }
-          },
-          "400": {
-            "description": "Invalid tag value"
-          }
-        }
-      }
     }
   },
   "responses": {
         }
       }
     },
-    "Component": {
-      "type": "object",
-      "properties": {
-        "compId": {
-          "type": "integer"
-        },
-        "cname": {
-          "type": "string",
-          "description": "component namespace name"
-        },
-        "dname": {
-          "type": "string",
-          "description": "component display name"
-        }
-      }
-    },
     "ComponentInput": {
       "type": "object",
       "properties": {
     "description": "Find out more about Swagger",
     "url": "http://swagger.io"
   }
-}
+}
\ No newline at end of file
index 9e221cd..a43f85c 100644 (file)
 
 # Properties for the ONAP Controller Dashboard webapp
 
-# Set to true to use local copies of controller data 
-controller.mock.data = false
+# dashboard.properties
 
-# for ONAP or other type
-controller.type = os
+# Properties for the Dashboard webapp
 
+# YAML would represent this more elegantly, but Spring likes properties.
+# Controllers - a key for each set of properties "key.propKey" below.
 controller.env = dev
 
-# YAML would represent this more elegantly, but Spring likes properties.
-controller.key.list = dev
+controller.site.list = primary
 
-dev.name = Local
-dev.url = https://dashboard.onap.svc.cluster.local/api/v3.1
-dev.inventory.url = https://inventory.onap.svc.cluster.local:8443/
-dev.dhandler.url = https://dplh.onap.svc.cluster.local:8443/
-dev.consul.url = https://cnsl.onap.svc.cluster.local:9500/
+site.primary.name = mtn23a 
+site.primary.cloudify.url = https://eom-orcl-d14.ecomp.idns.cip.att.com/api/v3.1
+site.primary.consul.url = https://eom-cnsl-d14.ecomp.idns.cip.att.com:9500/
+site.primary.inventory.url = https://eom-invt-d14.ecomp.idns.cip.att.com:30123 
+site.primary.dhandler.url = https://eom-dplh-d14.ecomp.idns.cip.att.com:30125/
+site.primary.dbcl.url = https://ecompc-dbclgui-dev-s5.ecomp.idns.cip.att.com:30162/dmaap-bc-app/doLogin 
+site.primary.feed_m.url = https://feedM.com 
+site.primary.cloudify.username = admin
+site.primary.cloudify.password = Cloudify_local
+site.primary.cloudify.is_encrypted = false
 
-dev.username = admin
-dev.password =  admin
-dev.is_encrypted = false
 
index b0b63dd..f54662f 100644 (file)
@@ -24,6 +24,9 @@
        final String appDisplayName = SystemProperties.containsProperty(SystemProperties.APP_DISPLAY_NAME)\r
                        ? SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME)\r
                        : SystemProperties.APP_DISPLAY_NAME;\r
+    String signUpPage = "signup.htm";\r
+       String signupUrl = (request.isSecure() ? "https://" : "http://") + request.getServerName() + ":"\r
+                               + request.getServerPort() + request.getContextPath() + "/" + signUpPage;\r
 %>\r
 \r
 <html>\r
                        margin-left: auto;\r
                        margin-right: auto;\r
                }\r
+        .formIn {\r
+            width: 200px;\r
+            height:25px;\r
+            border-radius: 4px;\r
+            font-size:18px;\r
+            padding-left:5px;\r
+            background-color: #f1ecec;\r
+        }\r
+        #regLink {\r
+          background: #0081a4;\r
+          border-radius: 3px;\r
+          padding: 4px;\r
+          font-size: large;\r
+          font-weight: bold;\r
+          text-decoration: none;\r
+          color: black;\r
+        }\r
+        #formDiv {\r
+          background-color: #0081a4b0;\r
+          width: 300px;\r
+          margin-left: auto;\r
+          margin-right: auto;\r
+          padding-bottom: 10px;\r
+        }\r
                </style>\r
        </head>\r
        <body>\r
                        <h2>\r
                                <%=appDisplayName%>\r
                        </h2>\r
-                       <br />\r
-                       <form action="login_external" method="POST"> \r
-                               <label for="loginId">Login ID:</label>\r
-                               <input id="loginId" name="loginId" type="text" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;" maxlength="30">\r
-                               <br/>\r
-                               <br/>\r
-                               <label for="password">Password:</label>\r
-                               <input id="password" name="password" type="password" style="width: 140px;height:25px;border-radius:7px;font-size:18px;padding-left:5px;"\r
-                                                       maxlength="30" >\r
-                               <br />\r
-                               <br />\r
-                               <input id="loginBtn" type="submit" alt="Login" value="Login">\r
-                       </form>\r
+            <div id="formDiv">\r
+            <form action="login_external" method="POST"> \r
+                <h3> Login </h3>\r
+                               <input class="formIn" id="loginId" name="loginId" type="text" maxlength="30" placeholder="User ID">\r
+                               <br>\r
+                               <br>\r
+                               <input class="formIn" id="password" name="password" type="password" maxlength="30" placeholder="Password">\r
+                               <br>\r
+                               <br>\r
+                               <input id="loginBtn" type="submit" alt="Login" value="LOG IN" style="width: 200px; font-weight: bolder;">\r
+                       </form> \r
+            <br>   \r
+            <p>Not registered yet? <a id="regLink" href="<%=signupUrl%>">Sign up</a></p>\r
+            </div>\r
                </div>\r
                <br />\r
                <br />\r
diff --git a/ccsdk-app-os/src/main/webapp/WEB-INF/jsp/signup.jsp b/ccsdk-app-os/src/main/webapp/WEB-INF/jsp/signup.jsp
new file mode 100644 (file)
index 0000000..421f72a
--- /dev/null
@@ -0,0 +1,128 @@
+<%@ page import="org.onap.portalsdk.core.util.SystemProperties"%>
+<!DOCTYPE html>
+<%
+       // Name is defined by app; do not throw if missing
+       final String appDisplayName = SystemProperties.containsProperty(SystemProperties.APP_DISPLAY_NAME)
+                       ? SystemProperties.getProperty(SystemProperties.APP_DISPLAY_NAME)
+                       : SystemProperties.APP_DISPLAY_NAME;
+    String loginPage = "login_external.htm";
+       String loginUrl = (request.isSecure() ? "https://" : "http://") + request.getServerName() + ":"
+                               + request.getServerPort() + request.getContextPath() + "/" + loginPage;
+%>
+<html>
+<head>
+<meta charset="ISO-8859-1">
+<title>Sign up / Register</title>
+<style>
+    html {
+      font-family: Verdana, Arial, Helvetica, sans-serif;
+    }
+    body {
+      padding-top: 15px;
+    }
+    .logo {
+      position: fixed;
+      left: 15px;
+      top: 15px;
+      z-index: -1;
+    }
+    .loginError {
+      font-size: 18px;
+      color: red;
+      text-align: center;
+    }
+    .login {
+      font-size: 16px;
+      display: block;
+      margin-left: auto;
+      margin-right: auto;
+      text-align: center;
+      width: 100%;
+    }
+    .login input[type=submit] {
+      font-size: 16px;
+    }
+    .terms {
+      font-size: 10px;
+      text-align: center;
+      margin-left: auto;
+      margin-right: auto;
+    }
+    .terms a {
+      font-size: 10px;
+      text-align: center;
+      margin-left: auto;
+      margin-right: auto;
+    }
+    .formIn {
+        width: 200px;
+        height:25px;
+        border-radius: 4px;
+        font-size:18px;
+        padding-left:5px;
+        background-color: #f1ecec;
+    }
+    #regLink {
+    background: #0081a4;
+    border-radius: 3px;
+    padding: 4px;
+    font-size: large;
+    font-weight: bold;
+    text-decoration: none;
+    color: black;
+    }
+    #formDiv {
+    background-color: #0081a4b0;
+    width: 300px;
+    margin-left: auto;
+    margin-right: auto;
+    padding-bottom: 10px;
+    }
+    </style>
+
+</head>
+<body>
+    <div class="login">
+      <img src="app/ccsdk/images/onap_logo_2257x496.png" style="height: 150px;" />
+      <h2>
+        <%=appDisplayName%>
+      </h2>
+      <div id="formDiv">
+      <form action="signup" method="POST"> 
+        <h3>Sign Up</h3>
+        <input id="first" class="formIn" name="first" type="text" maxlength="30" placeholder="First Name">
+        <br/>
+        <br/>
+        <input id="last" class="formIn" name="last" type="text" maxlength="30" placeholder="Last Name">
+        <br/>
+        <br/>
+        <input id="loginId" class="formIn" name="loginId" type="text" maxlength="30" placeholder="User ID">
+        <br/>
+        <br/>
+        <input id="password" class="formIn" name="password" type="password" maxlength="30" placeholder="Password">
+        <br />
+        <br />
+        <input id="email" class="formIn" name="email" type="text" maxlength="30" placeholder="Email">
+        <br />
+        <br />
+        <input id="loginBtn" type="submit" alt="Login" value="SIGN UP" style="width: 200px; font-weight: bolder;">
+      </form>  
+      <br>
+              <p>Already registered? <a id="regLink" href="<%=loginUrl%>"> Login</a></p> 
+       </div>  
+    </div>
+    <br />
+    <br />
+    <div class="loginError">${model.error}</div>
+    <br />
+    <br />
+    <br />
+    <div id="footer">
+      <div class="terms">
+           <p class="copyright-text">
+            &copy; 2020 ONAP. The Linux Foundation.         
+           </p> 
+      </div>
+    </div>
+</body>
+</html>
\ No newline at end of file
diff --git a/ccsdk-app-os/src/main/webapp/WEB-INF/oom-app-definitions.xml b/ccsdk-app-os/src/main/webapp/WEB-INF/oom-app-definitions.xml
new file mode 100644 (file)
index 0000000..5fcc6c8
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    =============LICENSE_START=========================================================
+   
+    =================================================================================
+     Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
+    ================================================================================
+     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.
+    ============LICENSE_END=========================================================
+   
+     ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ -->
+
+<!DOCTYPE tiles-definitions PUBLIC
+       "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
+       "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
+<tiles-definitions>
+
+       <!-- Main page for the single-page app -->
+    <definition name="ecd_home_tdkey"   template="/app/ccsdk/home/oom_spa.html"/>
+       <definition name="welcome"
+               template="/app/fusion/scripts/DS2-view-models/welcome.html" />
+</tiles-definitions>
index e5c5dfc..9a7d498 100644 (file)
@@ -1500,7 +1500,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
                <ul class="toc-list-h1">
         
           <li>
-            <a href="#dcae-dashboard-api" class="toc-h1 toc-link" data-title="DCAE Dashboard API v1.0.0">DCAE Dashboard API v1.0.0</a>
+            <a href="#dcae-dashboard-api" class="toc-h1 toc-link" data-title="DCAE Dashboard API v1.4.0">DCAE Dashboard API v1.4.0</a>
             
           </li>
         
@@ -1510,27 +1510,22 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
               <ul class="toc-list-h2">
                 
                   <li>
-                    <a href="#find-all-blueprint-templates" class="toc-h2 toc-link" data-title="">Find all blueprint templates</a>
+                    <a href="#list-blueprints" class="toc-h2 toc-link" data-title="">List Blueprints</a>
                     
                   </li>
                 
                   <li>
-                    <a href="#create-upload-a-new-blueprint-template" class="toc-h2 toc-link" data-title="">Create/Upload a new blueprint template</a>
+                    <a href="#create-blueprint" class="toc-h2 toc-link" data-title="">Create Blueprint</a>
                     
                   </li>
                 
                   <li>
-                    <a href="#delete-a-blueprint-template" class="toc-h2 toc-link" data-title="">Delete a blueprint template</a>
+                    <a href="#delete-blueprint" class="toc-h2 toc-link" data-title="">Delete Blueprint</a>
                     
                   </li>
                 
                   <li>
-                    <a href="#get-services-mapped-to-a-blueprint-template" class="toc-h2 toc-link" data-title="">Get Services mapped to a blueprint template</a>
-                    
-                  </li>
-                
-                  <li>
-                    <a href="#find-a-blueprint-by-a-name-pattern" class="toc-h2 toc-link" data-title="">Find a blueprint by a name pattern</a>
+                    <a href="#get-deployments-for-a-blueprint" class="toc-h2 toc-link" data-title="">Get Deployments for a blueprint</a>
                     
                   </li>
                 
@@ -1544,47 +1539,42 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
               <ul class="toc-list-h2">
                 
                   <li>
-                    <a href="#lists-all-deployments" class="toc-h2 toc-link" data-title="">Lists all Deployments</a>
-                    
-                  </li>
-                
-                  <li>
-                    <a href="#initiate-a-deployment--install--operation-for-an-application-or-service" class="toc-h2 toc-link" data-title="">Initiate a deployment (install) operation for an application or service</a>
+                    <a href="#list-deployments" class="toc-h2 toc-link" data-title="">List Deployments</a>
                     
                   </li>
                 
                   <li>
-                    <a href="#initiate-an-uninstall-operation-for-an-application-or-service" class="toc-h2 toc-link" data-title="">Initiate an uninstall operation for an application or service</a>
+                    <a href="#create-deployment" class="toc-h2 toc-link" data-title="">Create Deployment</a>
                     
                   </li>
                 
                   <li>
-                    <a href="#upgrade-or-rollback-an-existing-deployment-using-cloudify-helm-plugin" class="toc-h2 toc-link" data-title="">Upgrade or Rollback an existing deployment using Cloudify Helm plugin</a>
+                    <a href="#delete-deployment" class="toc-h2 toc-link" data-title="">Delete Deployment</a>
                     
                   </li>
                 
                   <li>
-                    <a href="#gets-a-deployment" class="toc-h2 toc-link" data-title="">Gets a Deployment</a>
+                    <a href="#upgrade_rollback-deployment" class="toc-h2 toc-link" data-title="">Upgrade_Rollback Deployment</a>
                     
                   </li>
                 
                   <li>
-                    <a href="#update-an-existing-deployment" class="toc-h2 toc-link" data-title="">Update an existing deployment</a>
+                    <a href="#get-deployment" class="toc-h2 toc-link" data-title="">Get Deployment</a>
                     
                   </li>
                 
                   <li>
-                    <a href="#deployment-execution-status" class="toc-h2 toc-link" data-title="">Deployment execution status</a>
+                    <a href="#deployment-status" class="toc-h2 toc-link" data-title="">Deployment Status</a>
                     
                   </li>
                 
                   <li>
-                    <a href="#deployment-health-status" class="toc-h2 toc-link" data-title="">Deployment health status</a>
+                    <a href="#deployment-health" class="toc-h2 toc-link" data-title="">Deployment health</a>
                     
                   </li>
                 
                   <li>
-                    <a href="#deployment-inputs" class="toc-h2 toc-link" data-title="">Deployment inputs</a>
+                    <a href="#deployment-inputs" class="toc-h2 toc-link" data-title="">Deployment Inputs</a>
                     
                   </li>
                 
@@ -1598,26 +1588,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
               <ul class="toc-list-h2">
                 
                   <li>
-                    <a href="#lists-all-cloudify-tenants" class="toc-h2 toc-link" data-title="">Lists all Cloudify Tenants</a>
-                    
-                  </li>
-                
-              </ul>
-            
-          </li>
-        
-          <li>
-            <a href="#dcae-dashboard-api-components" class="toc-h1 toc-link" data-title="Components">Components</a>
-            
-              <ul class="toc-list-h2">
-                
-                  <li>
-                    <a href="#lists-all-application-components" class="toc-h2 toc-link" data-title="">Lists all application components</a>
-                    
-                  </li>
-                
-                  <li>
-                    <a href="#add-an-application-component" class="toc-h2 toc-link" data-title="">add an application component</a>
+                    <a href="#list-tenants" class="toc-h2 toc-link" data-title="">List Tenants</a>
                     
                   </li>
                 
@@ -1635,11 +1606,6 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
                     
                   </li>
                 
-                  <li>
-                    <a href="#tocscomponent" class="toc-h2 toc-link" data-title="">Component</a>
-                    
-                  </li>
-                
                   <li>
                     <a href="#tocscomponentinput" class="toc-h2 toc-link" data-title="">ComponentInput</a>
                     
@@ -1747,7 +1713,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
     <div class="page-wrapper">
       <div class="dark-box"></div>
       <div class="content">
-        <h1 id="dcae-dashboard-api">DCAE Dashboard API v1.0.0</h1>
+        <h1 id="dcae-dashboard-api">DCAE Dashboard API v1.4.0</h1>
 <blockquote>
 <p>Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.</p>
 </blockquote>
@@ -1755,16 +1721,16 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
 <p>Base URLs:</p>
 <ul>
 <li>
-<p><a href="https://dcae-dashboard:8080/ccsdk-app/nb-api">https://dcae-dashboard:8080/ccsdk-app/nb-api</a></p>
+<p><a href="https://dcae-dashboard:8080/ccsdk-app/nb-api/v2">https://dcae-dashboard:8080/ccsdk-app/nb-api/v2</a></p>
 </li>
 <li>
-<p><a href="http://dcae-dashboard:8080/ccsdk-app/nb-api">http://dcae-dashboard:8080/ccsdk-app/nb-api</a></p>
+<p><a href="http://dcae-dashboard:8080/ccsdk-app/nb-api/v2">http://dcae-dashboard:8080/ccsdk-app/nb-api/v2</a></p>
 </li>
 </ul>
 <p>Email: <a href="mailto:rp5662@att.com">Support</a></p>
 <h1 id="dcae-dashboard-api-blueprints">Blueprints</h1>
 <p>Query blueprint information</p>
-<h2 id="find-all-blueprint-templates">Find all blueprint templates</h2>
+<h2 id="list-blueprints">List Blueprints</h2>
 <p><a id="opIdList Blueprints"></a></p>
 <blockquote>
 <p>Code samples</p>
@@ -1774,7 +1740,7 @@ headers = {
   <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
 }
 
-r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints'</span>, params={
+r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints'</span>, params={
   <span class="hljs-string">'pageNum'</span>: <span class="hljs-string">'string'</span>,  <span class="hljs-string">'viewPerPage'</span>: <span class="hljs-string">'string'</span>
 }, headers = headers)
 
@@ -1782,13 +1748,14 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints?pageNum=string&amp;viewPerPage=string \
+curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints?pageNum=string&amp;viewPerPage=string \
   -H <span class="hljs-string">'Accept: application/json'</span>
 
 </code></pre>
 <p><code>GET /blueprints</code></p>
+<p><em>Find all blueprint templates</em></p>
 <p>Fetch the blueprints data from inventory</p>
-<h3 id="find-all-blueprint-templates-parameters">Parameters</h3>
+<h3 id="list-blueprints-parameters">Parameters</h3>
 <table>
 <thead>
 <tr>
@@ -1917,13 +1884,13 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints?pageNum=stri
         },
         <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
       },
-      <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-      <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>
+      <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+      <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>
     }
   ]
 }
 </code></pre>
-<h3 id="find-all-blueprint-templates-responses">Responses</h3>
+<h3 id="list-blueprints-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -1951,7 +1918,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints?pageNum=stri
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h2 id="create-upload-a-new-blueprint-template">Create/Upload a new blueprint template</h2>
+<h2 id="create-blueprint">Create Blueprint</h2>
 <p><a id="opIdCreate Blueprint"></a></p>
 <blockquote>
 <p>Code samples</p>
@@ -1962,7 +1929,7 @@ headers = {
   <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
 }
 
-r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints'</span>, params={
+r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints'</span>, params={
 
 }, headers = headers)
 
@@ -1970,12 +1937,13 @@ r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-a
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints \
+curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints \
   -H <span class="hljs-string">'Content-Type: application/json'</span> \
   -H <span class="hljs-string">'Accept: application/json'</span>
 
 </code></pre>
 <p><code>POST /blueprints</code></p>
+<p><em>Create/Upload a new blueprint template</em></p>
 <p>Upload a new blueprint template into inventory</p>
 <blockquote>
 <p>Body parameter</p>
@@ -1989,7 +1957,7 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints \
   <span class="hljs-attr">"component"</span>: <span class="hljs-string">"string"</span>
 }
 </code></pre>
-<h3 id="create-upload-a-new-blueprint-template-parameters">Parameters</h3>
+<h3 id="create-blueprint-parameters">Parameters</h3>
 <table>
 <thead>
 <tr>
@@ -2081,13 +2049,13 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints \
         },
         <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
       },
-      <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-      <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>
+      <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+      <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>
     }
   ]
 }
 </code></pre>
-<h3 id="create-upload-a-new-blueprint-template-responses">Responses</h3>
+<h3 id="create-blueprint-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -2115,14 +2083,14 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints \
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h2 id="delete-a-blueprint-template">Delete a blueprint template</h2>
+<h2 id="delete-blueprint">Delete Blueprint</h2>
 <p><a id="opIdDelete Blueprint"></a></p>
 <blockquote>
 <p>Code samples</p>
 </blockquote>
 <pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests
 
-r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}'</span>, params={
+r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints/{typeId}'</span>, params={
 
 )
 
@@ -2130,12 +2098,13 @@ r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}
+curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints/{typeId}
 
 </code></pre>
 <p><code>DELETE /blueprints/{typeId}</code></p>
+<p><em>Delete a blueprint template</em></p>
 <p>Delete a blueprint template from inventory</p>
-<h3 id="delete-a-blueprint-template-parameters">Parameters</h3>
+<h3 id="delete-blueprint-parameters">Parameters</h3>
 <table>
 <thead>
 <tr>
@@ -2156,7 +2125,7 @@ curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}
 </tr>
 </tbody>
 </table>
-<h3 id="delete-a-blueprint-template-responses">Responses</h3>
+<h3 id="delete-blueprint-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -2178,14 +2147,14 @@ curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h2 id="get-services-mapped-to-a-blueprint-template">Get Services mapped to a blueprint template</h2>
+<h2 id="get-deployments-for-a-blueprint">Get Deployments for a blueprint</h2>
 <p><a id="opIdGet Deployments for a blueprint"></a></p>
 <blockquote>
 <p>Code samples</p>
 </blockquote>
 <pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests
 
-r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}/services'</span>, params={
+r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints/{typeId}/services'</span>, params={
 
 )
 
@@ -2193,12 +2162,13 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}/services
+curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/blueprints/{typeId}/services
 
 </code></pre>
 <p><code>GET /blueprints/{typeId}/services</code></p>
+<p><em>Get Services mapped to a blueprint template</em></p>
 <p>Get Deployment References existing for a blueprint</p>
-<h3 id="get-services-mapped-to-a-blueprint-template-parameters">Parameters</h3>
+<h3 id="get-deployments-for-a-blueprint-parameters">Parameters</h3>
 <table>
 <thead>
 <tr>
@@ -2219,7 +2189,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}/ser
 </tr>
 </tbody>
 </table>
-<h3 id="get-services-mapped-to-a-blueprint-template-responses">Responses</h3>
+<h3 id="get-deployments-for-a-blueprint-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -2241,189 +2211,9 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/{typeId}/ser
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h2 id="find-a-blueprint-by-a-name-pattern">Find a blueprint by a name pattern</h2>
-<p><a id="opIdGet Blueprint"></a></p>
-<blockquote>
-<p>Code samples</p>
-</blockquote>
-<pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests
-headers = {
-  <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
-}
-
-r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/findByName'</span>, params={
-  <span class="hljs-string">'name'</span>: <span class="hljs-string">'string'</span>
-}, headers = headers)
-
-<span class="hljs-keyword">print</span> r.json()
-
-</code></pre>
-<pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/blueprints/findByName?name=string \
-  -H <span class="hljs-string">'Accept: application/json'</span>
-
-</code></pre>
-<p><code>GET /blueprints/findByName</code></p>
-<p>Fetch the blueprint objects from inventory whose names match a string pattern</p>
-<h3 id="find-a-blueprint-by-a-name-pattern-parameters">Parameters</h3>
-<table>
-<thead>
-<tr>
-<th>Name</th>
-<th>In</th>
-<th>Type</th>
-<th>Required</th>
-<th>Description</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>name</td>
-<td>query</td>
-<td>string</td>
-<td>true</td>
-<td>name pattern to filter by</td>
-</tr>
-<tr>
-<td>_include</td>
-<td>query</td>
-<td>array[string]</td>
-<td>false</td>
-<td>blueprint object properties need to be considered for filter</td>
-</tr>
-</tbody>
-</table>
-<h4 id="enumerated-values">Enumerated Values</h4>
-<table>
-<thead>
-<tr>
-<th>Parameter</th>
-<th>Value</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>_include</td>
-<td>typeName</td>
-</tr>
-<tr>
-<td>_include</td>
-<td>typeId</td>
-</tr>
-<tr>
-<td>_include</td>
-<td>typeVersion</td>
-</tr>
-</tbody>
-</table>
-<blockquote>
-<p>Example responses</p>
-</blockquote>
-<blockquote>
-<p>200 Response</p>
-</blockquote>
-<pre class="highlight tab tab-json"><code>{
-  <span class="hljs-attr">"links"</span>: {
-    <span class="hljs-attr">"previousLink"</span>: {
-      <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
-      <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>,
-      <span class="hljs-attr">"uri"</span>: <span class="hljs-string">"http://example.com"</span>,
-      <span class="hljs-attr">"uriBuilder"</span>: {},
-      <span class="hljs-attr">"rels"</span>: [
-        <span class="hljs-string">"string"</span>
-      ],
-      <span class="hljs-attr">"params"</span>: {
-        <span class="hljs-attr">"property1"</span>: <span class="hljs-string">"string"</span>,
-        <span class="hljs-attr">"property2"</span>: <span class="hljs-string">"string"</span>
-      },
-      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
-    },
-    <span class="hljs-attr">"nextLink"</span>: {
-      <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
-      <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>,
-      <span class="hljs-attr">"uri"</span>: <span class="hljs-string">"http://example.com"</span>,
-      <span class="hljs-attr">"uriBuilder"</span>: {},
-      <span class="hljs-attr">"rels"</span>: [
-        <span class="hljs-string">"string"</span>
-      ],
-      <span class="hljs-attr">"params"</span>: {
-        <span class="hljs-attr">"property1"</span>: <span class="hljs-string">"string"</span>,
-        <span class="hljs-attr">"property2"</span>: <span class="hljs-string">"string"</span>
-      },
-      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
-    }
-  },
-  <span class="hljs-attr">"totalCount"</span>: <span class="hljs-number">0</span>,
-  <span class="hljs-attr">"items"</span>: [
-    {
-      <span class="hljs-attr">"owner"</span>: <span class="hljs-string">"string"</span>,
-      <span class="hljs-attr">"typeName"</span>: <span class="hljs-string">"string"</span>,
-      <span class="hljs-attr">"typeVersion"</span>: <span class="hljs-number">0</span>,
-      <span class="hljs-attr">"blueprintTemplate"</span>: <span class="hljs-string">"string"</span>,
-      <span class="hljs-attr">"serviceIds"</span>: [
-        <span class="hljs-string">"string"</span>
-      ],
-      <span class="hljs-attr">"vnfTypes"</span>: [
-        <span class="hljs-string">"string"</span>
-      ],
-      <span class="hljs-attr">"serviceLocations"</span>: [
-        <span class="hljs-string">"string"</span>
-      ],
-      <span class="hljs-attr">"asdcServiceId"</span>: <span class="hljs-string">"string"</span>,
-      <span class="hljs-attr">"asdcResourceId"</span>: <span class="hljs-string">"string"</span>,
-      <span class="hljs-attr">"asdcServiceURL"</span>: <span class="hljs-string">"string"</span>,
-      <span class="hljs-attr">"typeId"</span>: <span class="hljs-string">"string"</span>,
-      <span class="hljs-attr">"selfLink"</span>: {
-        <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
-        <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>,
-        <span class="hljs-attr">"uri"</span>: <span class="hljs-string">"http://example.com"</span>,
-        <span class="hljs-attr">"uriBuilder"</span>: {},
-        <span class="hljs-attr">"rels"</span>: [
-          <span class="hljs-string">"string"</span>
-        ],
-        <span class="hljs-attr">"params"</span>: {
-          <span class="hljs-attr">"property1"</span>: <span class="hljs-string">"string"</span>,
-          <span class="hljs-attr">"property2"</span>: <span class="hljs-string">"string"</span>
-        },
-        <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
-      },
-      <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-      <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>
-    }
-  ]
-}
-</code></pre>
-<h3 id="find-a-blueprint-by-a-name-pattern-responses">Responses</h3>
-<table>
-<thead>
-<tr>
-<th>Status</th>
-<th>Meaning</th>
-<th>Description</th>
-<th>Schema</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>200</td>
-<td><a href="https://tools.ietf.org/html/rfc7231#section-6.3.1">OK</a></td>
-<td>List of <code>DCAEServiceType</code> objects</td>
-<td><a href="#schemainlineresponse200">InlineResponse200</a></td>
-</tr>
-<tr>
-<td>400</td>
-<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.1">Bad Request</a></td>
-<td>Invalid tag value</td>
-<td>None</td>
-</tr>
-</tbody>
-</table>
-<aside class="success">
-This operation does not require authentication
-</aside>
 <h1 id="dcae-dashboard-api-deployments">Deployments</h1>
 <p>Manage deployments</p>
-<h2 id="lists-all-deployments">Lists all Deployments</h2>
+<h2 id="list-deployments">List Deployments</h2>
 <p><a id="opIdList Deployments"></a></p>
 <blockquote>
 <p>Code samples</p>
@@ -2433,7 +2223,7 @@ headers = {
   <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
 }
 
-r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments'</span>, params={
+r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments'</span>, params={
   <span class="hljs-string">'pageNum'</span>: <span class="hljs-string">'string'</span>,  <span class="hljs-string">'viewPerPage'</span>: <span class="hljs-string">'string'</span>
 }, headers = headers)
 
@@ -2441,13 +2231,14 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=string&amp;viewPerPage=string \
+curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments?pageNum=string&amp;viewPerPage=string \
   -H <span class="hljs-string">'Accept: application/json'</span>
 
 </code></pre>
 <p><code>GET /deployments</code></p>
+<p><em>List all Deployments</em></p>
 <p>Query all deployments or Service objects from Inventory</p>
-<h3 id="lists-all-deployments-parameters">Parameters</h3>
+<h3 id="list-deployments-parameters">Parameters</h3>
 <table>
 <thead>
 <tr>
@@ -2498,8 +2289,8 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=str
       },
       <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
     },
-    <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-    <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
+    <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+    <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
     <span class="hljs-attr">"typeLink"</span>: {
       <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
       <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>,
@@ -2549,8 +2340,8 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=str
           },
           <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
         },
-        <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-        <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
+        <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+        <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
         <span class="hljs-attr">"componentType"</span>: <span class="hljs-string">"string"</span>,
         <span class="hljs-attr">"componentSource"</span>: <span class="hljs-string">"DCAEController"</span>,
         <span class="hljs-attr">"status"</span>: <span class="hljs-string">"string"</span>,
@@ -2562,7 +2353,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=str
   }
 ]
 </code></pre>
-<h3 id="lists-all-deployments-responses">Responses</h3>
+<h3 id="list-deployments-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -2587,7 +2378,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=str
 </tr>
 </tbody>
 </table>
-<h3 id="lists-all-deployments-responseschema">Response Schema</h3>
+<h3 id="list-deployments-responseschema">Response Schema</h3>
 <p>Status Code <strong>200</strong></p>
 <table>
 <thead>
@@ -2834,7 +2625,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments?pageNum=str
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h2 id="initiate-a-deployment--install--operation-for-an-application-or-service">Initiate a deployment (install) operation for an application or service</h2>
+<h2 id="create-deployment">Create Deployment</h2>
 <p><a id="opIdCreate Deployment"></a></p>
 <blockquote>
 <p>Code samples</p>
@@ -2845,7 +2636,7 @@ headers = {
   <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
 }
 
-r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments'</span>, params={
+r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments'</span>, params={
 
 }, headers = headers)
 
@@ -2853,12 +2644,13 @@ r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-a
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments \
+curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments \
   -H <span class="hljs-string">'Content-Type: application/json'</span> \
   -H <span class="hljs-string">'Accept: application/json'</span>
 
 </code></pre>
 <p><code>POST /deployments</code></p>
+<p><em>Initiate a deployment (install) operation for an application or service</em></p>
 <p>Controller sends the blueprint and required inputs to Deployment Handler microservice to initiate the deployment process</p>
 <blockquote>
 <p>Body parameter</p>
@@ -2873,7 +2665,7 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments \
   <span class="hljs-attr">"inputs"</span>: {}
 }
 </code></pre>
-<h3 id="initiate-a-deployment--install--operation-for-an-application-or-service-parameters">Parameters</h3>
+<h3 id="create-deployment-parameters">Parameters</h3>
 <table>
 <thead>
 <tr>
@@ -2909,7 +2701,7 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments \
   }
 }
 </code></pre>
-<h3 id="initiate-a-deployment--install--operation-for-an-application-or-service-responses">Responses</h3>
+<h3 id="create-deployment-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -2937,7 +2729,7 @@ curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments \
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h2 id="initiate-an-uninstall-operation-for-an-application-or-service">Initiate an uninstall operation for an application or service</h2>
+<h2 id="delete-deployment">Delete Deployment</h2>
 <p><a id="opIdDelete Deployment"></a></p>
 <blockquote>
 <p>Code samples</p>
@@ -2947,7 +2739,7 @@ headers = {
   <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
 }
 
-r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}'</span>, params={
+r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}'</span>, params={
   <span class="hljs-string">'tenant'</span>: <span class="hljs-string">'string'</span>
 }, headers = headers)
 
@@ -2955,13 +2747,14 @@ r = requests.delete(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}?tenant=string \
+curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}?tenant=string \
   -H <span class="hljs-string">'Accept: application/json'</span>
 
 </code></pre>
 <p><code>DELETE /deployments/{deploymentId}</code></p>
+<p><em>Initiate an uninstall operation for an application or service</em></p>
 <p>Controller sends the deployment reference to Deployment Handler microservice to initiate the uninstall process</p>
-<h3 id="initiate-an-uninstall-operation-for-an-application-or-service-parameters">Parameters</h3>
+<h3 id="delete-deployment-parameters">Parameters</h3>
 <table>
 <thead>
 <tr>
@@ -2997,7 +2790,7 @@ curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploym
 </blockquote>
 <pre class="highlight tab tab-json"><code><span class="hljs-string">"string"</span>
 </code></pre>
-<h3 id="initiate-an-uninstall-operation-for-an-application-or-service-responses">Responses</h3>
+<h3 id="delete-deployment-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -3025,7 +2818,7 @@ curl -X DELETE https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploym
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h2 id="upgrade-or-rollback-an-existing-deployment-using-cloudify-helm-plugin">Upgrade or Rollback an existing deployment using Cloudify Helm plugin</h2>
+<h2 id="upgrade_rollback-deployment">Upgrade_Rollback Deployment</h2>
 <p><a id="opIdUpgrade/Rollback Deployment"></a></p>
 <blockquote>
 <p>Code samples</p>
@@ -3035,7 +2828,7 @@ headers = {
   <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>
 }
 
-r = requests.put(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}'</span>, params={
+r = requests.put(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}'</span>, params={
 
 }, headers = headers)
 
@@ -3043,11 +2836,12 @@ r = requests.put(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId} \
+curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId} \
   -H <span class="hljs-string">'Content-Type: application/json'</span>
 
 </code></pre>
 <p><code>PUT /deployments/{deploymentId}</code></p>
+<p><em>Upgrade or Rollback an existing deployment using Cloudify Helm plugin</em></p>
 <p>Upgrade or Rollback an existing deployment using Cloudify Helm plugin</p>
 <blockquote>
 <p>Body parameter</p>
@@ -3061,7 +2855,7 @@ curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
   <span class="hljs-attr">"workflow"</span>: <span class="hljs-string">"string"</span>
 }
 </code></pre>
-<h3 id="upgrade-or-rollback-an-existing-deployment-using-cloudify-helm-plugin-parameters">Parameters</h3>
+<h3 id="upgrade_rollback-deployment-parameters">Parameters</h3>
 <table>
 <thead>
 <tr>
@@ -3089,7 +2883,7 @@ curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
 </tr>
 </tbody>
 </table>
-<h3 id="upgrade-or-rollback-an-existing-deployment-using-cloudify-helm-plugin-responses">Responses</h3>
+<h3 id="upgrade_rollback-deployment-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -3123,7 +2917,7 @@ curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h2 id="gets-a-deployment">Gets a Deployment</h2>
+<h2 id="get-deployment">Get Deployment</h2>
 <p><a id="opIdGet Deployment"></a></p>
 <blockquote>
 <p>Code samples</p>
@@ -3133,7 +2927,7 @@ headers = {
   <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
 }
 
-r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}'</span>, params={
+r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}'</span>, params={
 
 }, headers = headers)
 
@@ -3141,13 +2935,14 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId} \
+curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId} \
   -H <span class="hljs-string">'Accept: application/json'</span>
 
 </code></pre>
 <p><code>GET /deployments/{deploymentId}</code></p>
+<p><em>Get a Deployment</em></p>
 <p>Query a deployment or Service object from Inventory</p>
-<h3 id="gets-a-deployment-parameters">Parameters</h3>
+<h3 id="get-deployment-parameters">Parameters</h3>
 <table>
 <thead>
 <tr>
@@ -3191,8 +2986,8 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
       },
       <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
     },
-    <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-    <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
+    <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+    <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
     <span class="hljs-attr">"typeLink"</span>: {
       <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
       <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>,
@@ -3242,8 +3037,8 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
           },
           <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
         },
-        <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-        <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
+        <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+        <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
         <span class="hljs-attr">"componentType"</span>: <span class="hljs-string">"string"</span>,
         <span class="hljs-attr">"componentSource"</span>: <span class="hljs-string">"DCAEController"</span>,
         <span class="hljs-attr">"status"</span>: <span class="hljs-string">"string"</span>,
@@ -3255,7 +3050,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
   }
 ]
 </code></pre>
-<h3 id="gets-a-deployment-responses">Responses</h3>
+<h3 id="get-deployment-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -3280,7 +3075,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
 </tr>
 </tbody>
 </table>
-<h3 id="gets-a-deployment-responseschema">Response Schema</h3>
+<h3 id="get-deployment-responseschema">Response Schema</h3>
 <p>Status Code <strong>200</strong></p>
 <table>
 <thead>
@@ -3527,106 +3322,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h2 id="update-an-existing-deployment">Update an existing deployment</h2>
-<p><a id="opIdUpdate Deployment"></a></p>
-<blockquote>
-<p>Code samples</p>
-</blockquote>
-<pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests
-headers = {
-  <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>
-}
-
-r = requests.put(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/update'</span>, params={
-
-}, headers = headers)
-
-<span class="hljs-keyword">print</span> r.json()
-
-</code></pre>
-<pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X PUT https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/update \
-  -H <span class="hljs-string">'Content-Type: application/json'</span>
-
-</code></pre>
-<p><code>PUT /deployments/{deploymentId}/update</code></p>
-<p>Dispatch a request to Deployment handler mS to use Cloudify deployment update operation</p>
-<blockquote>
-<p>Body parameter</p>
-</blockquote>
-<pre class="highlight tab tab-json"><code>{
-  <span class="hljs-attr">"component"</span>: <span class="hljs-string">"string"</span>,
-  <span class="hljs-attr">"tag"</span>: <span class="hljs-string">"string"</span>,
-  <span class="hljs-attr">"blueprintId"</span>: <span class="hljs-string">"string"</span>,
-  <span class="hljs-attr">"blueprintName"</span>: <span class="hljs-string">"string"</span>,
-  <span class="hljs-attr">"blueprintVersion"</span>: <span class="hljs-number">0</span>,
-  <span class="hljs-attr">"tenant"</span>: <span class="hljs-string">"string"</span>,
-  <span class="hljs-attr">"inputs"</span>: {}
-}
-</code></pre>
-<h3 id="update-an-existing-deployment-parameters">Parameters</h3>
-<table>
-<thead>
-<tr>
-<th>Name</th>
-<th>In</th>
-<th>Type</th>
-<th>Required</th>
-<th>Description</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>deploymentId</td>
-<td>path</td>
-<td>string</td>
-<td>true</td>
-<td>ID of deployment to update</td>
-</tr>
-<tr>
-<td>body</td>
-<td>body</td>
-<td><a href="#schemadeploymentinput">DeploymentInput</a></td>
-<td>true</td>
-<td>Inputs to initiate a deployment: blueprint ID from inventory, Cloudify tenant name, blueprint inputs</td>
-</tr>
-</tbody>
-</table>
-<h3 id="update-an-existing-deployment-responses">Responses</h3>
-<table>
-<thead>
-<tr>
-<th>Status</th>
-<th>Meaning</th>
-<th>Description</th>
-<th>Schema</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>400</td>
-<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.1">Bad Request</a></td>
-<td>Invalid ID supplied</td>
-<td>None</td>
-</tr>
-<tr>
-<td>404</td>
-<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.4">Not Found</a></td>
-<td>Deployment not found</td>
-<td>None</td>
-</tr>
-<tr>
-<td>405</td>
-<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.5">Method Not Allowed</a></td>
-<td>Validation exception</td>
-<td>None</td>
-</tr>
-</tbody>
-</table>
-<aside class="success">
-This operation does not require authentication
-</aside>
-<h2 id="deployment-execution-status">Deployment execution status</h2>
+<h2 id="deployment-status">Deployment Status</h2>
 <p><a id="opIdDeployment Status"></a></p>
 <blockquote>
 <p>Code samples</p>
@@ -3636,7 +3332,7 @@ headers = {
   <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
 }
 
-r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/executions'</span>, params={
+r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/executions'</span>, params={
   <span class="hljs-string">'tenant'</span>: <span class="hljs-string">'string'</span>
 }, headers = headers)
 
@@ -3644,13 +3340,14 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/executions?tenant=string \
+curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/executions?tenant=string \
   -H <span class="hljs-string">'Accept: application/json'</span>
 
 </code></pre>
 <p><code>GET /deployments/{deploymentId}/executions</code></p>
+<p><em>Deployment execution status</em></p>
 <p>Query deployment workflow execution status</p>
-<h3 id="deployment-execution-status-parameters">Parameters</h3>
+<h3 id="deployment-status-parameters">Parameters</h3>
 <table>
 <thead>
 <tr>
@@ -3695,7 +3392,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
   }
 ]
 </code></pre>
-<h3 id="deployment-execution-status-responses">Responses</h3>
+<h3 id="deployment-status-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -3720,7 +3417,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
 </tr>
 </tbody>
 </table>
-<h3 id="deployment-execution-status-responseschema">Response Schema</h3>
+<h3 id="deployment-status-responseschema">Response Schema</h3>
 <p>Status Code <strong>200</strong></p>
 <table>
 <thead>
@@ -3787,7 +3484,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h2 id="deployment-health-status">Deployment health status</h2>
+<h2 id="deployment-health">Deployment health</h2>
 <p><a id="opIdDeployment health"></a></p>
 <blockquote>
 <p>Code samples</p>
@@ -3797,7 +3494,7 @@ headers = {
   <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
 }
 
-r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/health'</span>, params={
+r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/health'</span>, params={
 
 }, headers = headers)
 
@@ -3805,13 +3502,14 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/health \
+curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/health \
   -H <span class="hljs-string">'Accept: application/json'</span>
 
 </code></pre>
 <p><code>GET /deployments/{deploymentId}/health</code></p>
+<p><em>Deployment health status</em></p>
 <p>Query consul for service health using deployment ID filter</p>
-<h3 id="deployment-health-status-parameters">Parameters</h3>
+<h3 id="deployment-health-parameters">Parameters</h3>
 <table>
 <thead>
 <tr>
@@ -3847,7 +3545,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
   <span class="hljs-attr">"serviceName"</span>: <span class="hljs-string">"string"</span>
 }
 </code></pre>
-<h3 id="deployment-health-status-responses">Responses</h3>
+<h3 id="deployment-health-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -3869,7 +3567,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deployment
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h2 id="deployment-inputs">Deployment inputs</h2>
+<h2 id="deployment-inputs">Deployment Inputs</h2>
 <p><a id="opIdDeployment Inputs"></a></p>
 <blockquote>
 <p>Code samples</p>
@@ -3879,7 +3577,7 @@ headers = {
   <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
 }
 
-r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/inputs'</span>, params={
+r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/inputs'</span>, params={
   <span class="hljs-string">'tenant'</span>: <span class="hljs-string">'string'</span>
 }, headers = headers)
 
@@ -3887,11 +3585,12 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/deployments/{deploymentId}/inputs?tenant=string \
+curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/deployments/{deploymentId}/inputs?tenant=string \
   -H <span class="hljs-string">'Accept: application/json'</span>
 
 </code></pre>
 <p><code>GET /deployments/{deploymentId}/inputs</code></p>
+<p><em>Deployment inputs</em></p>
 <p>Get blueprint inputs used to create deployment</p>
 <h3 id="deployment-inputs-parameters">Parameters</h3>
 <table>
@@ -3960,7 +3659,7 @@ This operation does not require authentication
 </aside>
 <h1 id="dcae-dashboard-api-tenants">Tenants</h1>
 <p>Query Cloudify Tenants</p>
-<h2 id="lists-all-cloudify-tenants">Lists all Cloudify Tenants</h2>
+<h2 id="list-tenants">List Tenants</h2>
 <p><a id="opIdList Tenants"></a></p>
 <blockquote>
 <p>Code samples</p>
@@ -3970,7 +3669,7 @@ headers = {
   <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
 }
 
-r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/tenants'</span>, params={
+r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/tenants'</span>, params={
 
 }, headers = headers)
 
@@ -3978,11 +3677,12 @@ r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-ap
 
 </code></pre>
 <pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/tenants \
+curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/v2/tenants \
   -H <span class="hljs-string">'Accept: application/json'</span>
 
 </code></pre>
 <p><code>GET /tenants</code></p>
+<p><em>Lists all Cloudify Tenants</em></p>
 <p>Query all Tenant names from Cloudify</p>
 <blockquote>
 <p>Example responses</p>
@@ -3996,7 +3696,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/tenants \
   }
 ]
 </code></pre>
-<h3 id="lists-all-cloudify-tenants-responses">Responses</h3>
+<h3 id="list-tenants-responses">Responses</h3>
 <table>
 <thead>
 <tr>
@@ -4021,7 +3721,7 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/tenants \
 </tr>
 </tbody>
 </table>
-<h3 id="lists-all-cloudify-tenants-responseschema">Response Schema</h3>
+<h3 id="list-tenants-responseschema">Response Schema</h3>
 <p>Status Code <strong>200</strong></p>
 <table>
 <thead>
@@ -4053,207 +3753,6 @@ curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/tenants \
 <aside class="success">
 This operation does not require authentication
 </aside>
-<h1 id="dcae-dashboard-api-components">Components</h1>
-<p>Query on-boarded components</p>
-<h2 id="lists-all-application-components">Lists all application components</h2>
-<p><a id="opIdList Components"></a></p>
-<blockquote>
-<p>Code samples</p>
-</blockquote>
-<pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests
-headers = {
-  <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>
-}
-
-r = requests.get(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/components'</span>, params={
-
-}, headers = headers)
-
-<span class="hljs-keyword">print</span> r.json()
-
-</code></pre>
-<pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X GET https://dcae-dashboard:8080/ccsdk-app/nb-api/components \
-  -H <span class="hljs-string">'Accept: application/json'</span>
-
-</code></pre>
-<p><code>GET /components</code></p>
-<p>Query all components from database</p>
-<blockquote>
-<p>Example responses</p>
-</blockquote>
-<blockquote>
-<p>200 Response</p>
-</blockquote>
-<pre class="highlight tab tab-json"><code>[
-  {
-    <span class="hljs-attr">"compId"</span>: <span class="hljs-number">0</span>,
-    <span class="hljs-attr">"cname"</span>: <span class="hljs-string">"string"</span>,
-    <span class="hljs-attr">"dname"</span>: <span class="hljs-string">"string"</span>
-  }
-]
-</code></pre>
-<h3 id="lists-all-application-components-responses">Responses</h3>
-<table>
-<thead>
-<tr>
-<th>Status</th>
-<th>Meaning</th>
-<th>Description</th>
-<th>Schema</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>200</td>
-<td><a href="https://tools.ietf.org/html/rfc7231#section-6.3.1">OK</a></td>
-<td>successful operation</td>
-<td>Inline</td>
-</tr>
-<tr>
-<td>400</td>
-<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.1">Bad Request</a></td>
-<td>Invalid status value</td>
-<td>None</td>
-</tr>
-</tbody>
-</table>
-<h3 id="lists-all-application-components-responseschema">Response Schema</h3>
-<p>Status Code <strong>200</strong></p>
-<table>
-<thead>
-<tr>
-<th>Name</th>
-<th>Type</th>
-<th>Required</th>
-<th>Restrictions</th>
-<th>Description</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td><em>anonymous</em></td>
-<td>[<a href="#schemacomponent">Component</a>]</td>
-<td>false</td>
-<td>none</td>
-<td>none</td>
-</tr>
-<tr>
-<td>» compId</td>
-<td>integer</td>
-<td>false</td>
-<td>none</td>
-<td>none</td>
-</tr>
-<tr>
-<td>» cname</td>
-<td>string</td>
-<td>false</td>
-<td>none</td>
-<td>component namespace name</td>
-</tr>
-<tr>
-<td>» dname</td>
-<td>string</td>
-<td>false</td>
-<td>none</td>
-<td>component display name</td>
-</tr>
-</tbody>
-</table>
-<aside class="success">
-This operation does not require authentication
-</aside>
-<h2 id="add-an-application-component">add an application component</h2>
-<p><a id="opIdAdd Component"></a></p>
-<blockquote>
-<p>Code samples</p>
-</blockquote>
-<pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests
-headers = {
-  <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>,
-  <span class="hljs-string">'Accept'</span>: <span class="hljs-string">'*/*'</span>
-}
-
-r = requests.post(<span class="hljs-string">'https://dcae-dashboard:8080/ccsdk-app/nb-api/components'</span>, params={
-
-}, headers = headers)
-
-<span class="hljs-keyword">print</span> r.json()
-
-</code></pre>
-<pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
-curl -X POST https://dcae-dashboard:8080/ccsdk-app/nb-api/components \
-  -H <span class="hljs-string">'Content-Type: application/json'</span> \
-  -H <span class="hljs-string">'Accept: */*'</span>
-
-</code></pre>
-<p><code>POST /components</code></p>
-<p>Insert a component into database</p>
-<blockquote>
-<p>Body parameter</p>
-</blockquote>
-<pre class="highlight tab tab-json"><code>{
-  <span class="hljs-attr">"cname"</span>: <span class="hljs-string">"string"</span>,
-  <span class="hljs-attr">"dname"</span>: <span class="hljs-string">"string"</span>
-}
-</code></pre>
-<h3 id="add-an-application-component-parameters">Parameters</h3>
-<table>
-<thead>
-<tr>
-<th>Name</th>
-<th>In</th>
-<th>Type</th>
-<th>Required</th>
-<th>Description</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>body</td>
-<td>body</td>
-<td><a href="#schemacomponentinput">ComponentInput</a></td>
-<td>true</td>
-<td>New component input</td>
-</tr>
-</tbody>
-</table>
-<blockquote>
-<p>Example responses</p>
-</blockquote>
-<blockquote>
-<p>200 Response</p>
-</blockquote>
-<h3 id="add-an-application-component-responses">Responses</h3>
-<table>
-<thead>
-<tr>
-<th>Status</th>
-<th>Meaning</th>
-<th>Description</th>
-<th>Schema</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>200</td>
-<td><a href="https://tools.ietf.org/html/rfc7231#section-6.3.1">OK</a></td>
-<td>successful operation</td>
-<td>Inline</td>
-</tr>
-<tr>
-<td>400</td>
-<td><a href="https://tools.ietf.org/html/rfc7231#section-6.5.1">Bad Request</a></td>
-<td>Invalid status value</td>
-<td>None</td>
-</tr>
-</tbody>
-</table>
-<h3 id="add-an-application-component-responseschema">Response Schema</h3>
-<aside class="success">
-This operation does not require authentication
-</aside>
 <h1 id="schemas">Schemas</h1>
 <h2 id="tocstenant">Tenant</h2>
 <p><a id="schematenant"></a></p>
@@ -4283,50 +3782,6 @@ This operation does not require authentication
 </tr>
 </tbody>
 </table>
-<h2 id="tocscomponent">Component</h2>
-<p><a id="schemacomponent"></a></p>
-<pre class="highlight tab tab-json"><code>{
-  <span class="hljs-attr">"compId"</span>: <span class="hljs-number">0</span>,
-  <span class="hljs-attr">"cname"</span>: <span class="hljs-string">"string"</span>,
-  <span class="hljs-attr">"dname"</span>: <span class="hljs-string">"string"</span>
-}
-
-</code></pre>
-<h3 id="properties">Properties</h3>
-<table>
-<thead>
-<tr>
-<th>Name</th>
-<th>Type</th>
-<th>Required</th>
-<th>Restrictions</th>
-<th>Description</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td>compId</td>
-<td>integer</td>
-<td>false</td>
-<td>none</td>
-<td>none</td>
-</tr>
-<tr>
-<td>cname</td>
-<td>string</td>
-<td>false</td>
-<td>none</td>
-<td>component namespace name</td>
-</tr>
-<tr>
-<td>dname</td>
-<td>string</td>
-<td>false</td>
-<td>none</td>
-<td>component display name</td>
-</tr>
-</tbody>
-</table>
 <h2 id="tocscomponentinput">ComponentInput</h2>
 <p><a id="schemacomponentinput"></a></p>
 <pre class="highlight tab tab-json"><code>{
@@ -4430,8 +3885,8 @@ This operation does not require authentication
         },
         <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
       },
-      <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-      <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>
+      <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+      <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>
     }
   ]
 }
@@ -4597,8 +4052,8 @@ This operation does not require authentication
     },
     <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
   },
-  <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-  <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
+  <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+  <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
   <span class="hljs-attr">"typeLink"</span>: {
     <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
     <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>,
@@ -4648,8 +4103,8 @@ This operation does not require authentication
         },
         <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
       },
-      <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-      <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
+      <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+      <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
       <span class="hljs-attr">"componentType"</span>: <span class="hljs-string">"string"</span>,
       <span class="hljs-attr">"componentSource"</span>: <span class="hljs-string">"DCAEController"</span>,
       <span class="hljs-attr">"status"</span>: <span class="hljs-string">"string"</span>,
@@ -4810,8 +4265,8 @@ This operation does not require authentication
         },
         <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
       },
-      <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-      <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
+      <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+      <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
       <span class="hljs-attr">"typeLink"</span>: {
         <span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
         <span class="hljs-attr">"rel"</span>: <span class="hljs-string">"string"</span>,
@@ -4861,8 +4316,8 @@ This operation does not require authentication
             },
             <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
           },
-          <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-          <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
+          <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+          <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
           <span class="hljs-attr">"componentType"</span>: <span class="hljs-string">"string"</span>,
           <span class="hljs-attr">"componentSource"</span>: <span class="hljs-string">"DCAEController"</span>,
           <span class="hljs-attr">"status"</span>: <span class="hljs-string">"string"</span>,
@@ -5024,8 +4479,8 @@ This operation does not require authentication
     },
     <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
   },
-  <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-  <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
+  <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+  <span class="hljs-attr">"modified"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
   <span class="hljs-attr">"componentType"</span>: <span class="hljs-string">"string"</span>,
   <span class="hljs-attr">"componentSource"</span>: <span class="hljs-string">"DCAEController"</span>,
   <span class="hljs-attr">"status"</span>: <span class="hljs-string">"string"</span>,
@@ -5232,8 +4687,8 @@ This operation does not require authentication
     },
     <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>
   },
-  <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>,
-  <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-02-05T21:21:26Z"</span>
+  <span class="hljs-attr">"created"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>,
+  <span class="hljs-attr">"deactivated"</span>: <span class="hljs-string">"2020-08-12T15:08:29Z"</span>
 }
 
 </code></pre>
diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/home/api_view.html b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/api_view.html
new file mode 100644 (file)
index 0000000..7561c73
--- /dev/null
@@ -0,0 +1,5 @@
+<div id="page-content">
+               <iframe  scrolling="yes" frameborder="0" style="width:100%; height: 800px;" 
+               ng-src="api-specs.html">
+       </iframe>
+</div>
\ No newline at end of file
diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/home/app-router.js b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/app-router.js
new file mode 100644 (file)
index 0000000..10337ba
--- /dev/null
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * =============LICENSE_START=========================================================
+ *
+ * =================================================================================
+ *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ *  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.
+ * ============LICENSE_END=========================================================
+ *
+ *******************************************************************************/
+appDS2.config(function($routeProvider) {
+  $routeProvider 
+  .when('/api', { 
+    templateUrl: 'app/ccsdk/home/api_view.html',
+    controller : ''
+  })
+  .when('/api-spec', { 
+    templateUrl: 'app/ccsdk/home/rest-api-spec.html',
+    controller : 'apiDocsController'
+  })
+  .when('/ibp', { 
+    templateUrl: 'app/ccsdk/inventory/inventory_blueprint_table.html',
+    controller : 'inventoryBlueprintTableController'
+  })
+  .when('/ibp/:bpId', { 
+    templateUrl: 'app/ccsdk/inventory/inventory_blueprint_table.html',
+    controller : 'inventoryBlueprintTableController'
+  })
+  .when('/idep', { 
+    templateUrl: 'app/ccsdk/cloudify/deployment_table.html',
+    controller : 'deploymentTableController'
+  })
+  .when('/idep/:depId', { 
+    templateUrl: 'app/ccsdk/cloudify/deployment_table.html',
+    controller : 'deploymentTableController'
+  })
+  .when('/iplug', { 
+    templateUrl: 'app/ccsdk/cloudify/plugin_table.html',
+    controller : 'PluginsTableController'
+  })
+  .when('/sh', { 
+    templateUrl: 'app/ccsdk/consul/service_health_table.html',
+    controller : 'serviceHealthTableController'
+  })
+  .when('/nh', { 
+    templateUrl: 'app/ccsdk/consul/node_table.html',
+    controller : 'nodeTableController'
+  })
+  .when('/dc', { 
+    templateUrl: 'app/ccsdk/consul/datacenter_table.html',
+    controller : 'datacenterTableController'
+  })
+  .when('/profile/:profileId', {
+    templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html',
+    controller: 'selfProfileController'
+  })
+  .when('/profile_search', {
+    templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/profile_searchDS2.html',
+    controller : "profileSearchCtrlDS2"
+  })
+  .when('/post_search', {
+    templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/post.html',
+    controller: 'postController'
+  })
+  .when('/self_profile', {
+    templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html',
+    controller: 'selfProfileController'
+  })  
+  .when('/role_list', {
+    templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/role_list.html',
+    controller : 'adminController'
+  })
+  .when('/role_function_list', {
+    templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/role-function.html',
+    controller : "adminController"
+  })
+  .when('/jcs_admin', {
+    templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/jcs_admin.html',
+    controller: 'adminController'
+  })
+  .when('/admin_menu_edit', {
+    templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/admin-menu-edit.html',
+    controller: 'AdminMenuEditController'
+  })
+  .when('/usage_list', {
+    templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/usage.html',
+    controller: 'usageListControllerDS2'
+  })
+  .otherwise({
+    templateUrl: 'app/ccsdk/home/executions_view.html',
+    controller : 'executionsViewController'
+  })
+  ;
+
+});
\ No newline at end of file
diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions-view-controller.js b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions-view-controller.js
new file mode 100644 (file)
index 0000000..fd2dd79
--- /dev/null
@@ -0,0 +1,415 @@
+appDS2.controller('executionsViewController', 
+    function($scope, $rootScope, ControllerService, $modal, ExecutionService, 
+        InventoryDeploymentService, DeploymentService, InventoryBlueprintService, 
+        InventoryExecutionService, localStorageService, $log, $interval) {
+       
+  var coll = document.getElementsByClassName("collapsible");
+  var i; 
+  for (i = 0; i < coll.length; i++) {
+    coll[i].addEventListener("click", function() {
+      this.classList.toggle("active");
+      var content = this.nextElementSibling;
+      if (content.style.display === "" || content.style.display === "block") {
+        content.style.display = "none";
+        content.style.maxHeight = null;
+      } else {
+        content.style.display = "block";
+        content.style.maxHeight = content.scrollHeight + "px";
+      }
+    });
+  }
+  var stop;
+       $scope.ecdapp = {};
+       $scope.ecdapp.isDataLoading = false;
+       $scope.ecdapp.appLabel = "";
+       $scope.ecdapp.bpCount = 0;
+       $scope.ecdapp.depCount = 0;
+       $scope.ecdapp.pluginCount = 0;
+       $scope.ecdapp.filterByUser = true;
+       $scope.ecdapp.searchByBp = 'owner:' + $scope.userId + ';';
+       $scope.ecdapp.searchByDep = 'owner:' + $scope.userId + ';';
+       $scope.ecdapp.bpObjList = [];
+       $scope.ecdapp.depObjList = [];
+       $scope.ecdapp.currentBpId = '';
+       $scope.ecdapp.currentDep;
+       $scope.ecdapp.isBpDataLoading = false;
+       $scope.ecdapp.isDepDataLoading = false;
+       $scope.ecdapp.isPluginDataLoading = false;
+       $scope.ecdapp.isExecDataLoading = false;
+       $scope.ecdapp.level_options = {
+           "off":"Group",
+           "on":"User"
+       };
+       $scope.ecdapp.inv_query_options = {
+             "off":"Off",
+             "on":"On"
+       };
+        
+  $scope.ecdapp.showingMoreFilters = false;
+
+  $scope.ecdapp.toggleMoreFilters = function() {      
+    $scope.ecdapp.showingMoreFilters = !$scope.ecdapp.showingMoreFilters;
+  };
+  $scope.ecdapp.availableStatus = 
+    ['pending','started','cancelling','force_cancelling','cancelled','terminated','failed'];
+  $scope.ecdapp.selectedStatus = 'started';
+       $scope.ecdapp.level_switch = {
+           value: true
+       };
+  $scope.ecdapp.inv_load = {
+        value: false
+  };
+  $scope.ecdapp.currentPage = 1;  
+  $scope.ecdapp.viewPerPage = 10;
+  $scope.ecdapp.selectedTenant = '';
+  $scope.ecdapp.execId = '';
+  
+       var debug = false;
+       
+  $scope.ecdapp.resetFilters = function() {
+    $scope.ecdapp.selectedTenant = '';
+    $scope.ecdapp.selectedStatus = '';
+  };
+  
+  $scope.ecdapp.extendedfilterSrch = function() {
+    $scope.ecdapp.showingMoreFilters = !$scope.ecdapp.showingMoreFilters;
+    $scope.ecdapp.searchExecTable();   
+  };
+  
+  $scope.ecdapp.searchExecTable = function() {
+    $scope.ecdapp.currentPage = 1;  
+    $scope.ecdapp.viewPerPage = 10;
+    if ($scope.ecdapp.execId != '') {
+      getExecutionForId();
+    } else {
+      if ($scope.ecdapp.selectedTenant == '') {
+        getActiveExecutions();
+      } else {
+        getPerTenantExecutions();
+      }
+    }
+  };
+
+  $scope.ecdapp.toggleUserFilt = function() {
+    if ($scope.ecdapp.level_switch.value) {
+      $scope.ecdapp.searchByBp = 'owner:' + $scope.userId + ';';
+      $scope.ecdapp.searchByDep = 'owner:' + $scope.userId + ';'; 
+    } else {
+      $scope.ecdapp.searchByBp = null;
+      $scope.ecdapp.searchByDep = null;
+    }
+    getBlueprintsCount();
+    getDeploymentsCount();
+  };
+  
+  $scope.$watch('ecdapp.inv_load["value"]', function(newValue,oldValue,scope) {
+    if (newValue != oldValue) {
+      if (newValue === true) {
+        $scope.ecdapp.toggleUserFilt();
+        $scope.ecdapp.searchExecTable(); 
+        stop = $interval( function(){ $scope.ecdapp.toggleUserFilt(); $scope.ecdapp.searchExecTable(); }, 60000, 100, false);
+      } else {
+        $scope.ecdapp.stopLoading();
+      }
+    }
+  }, true);
+  
+  $scope.ecdapp.stopLoading = function() {
+    if (angular.isDefined(stop)) {
+      $interval.cancel(stop);
+      stop = undefined;
+    }
+  };
+  
+       var getTenants = function() {  
+         var tenantStr = localStorageService.get('tenants');
+         if (!tenantStr) {
+           ControllerService.getTenants()
+                       .then(function(jsonObj) {
+                               if (jsonObj.error) {
+                                       $log.error("executionsViewController.getTenants failed: " + jsonObj.error);
+                                       $scope.ecdapp.isRequestFailed = true;
+                                       $scope.ecdapp.errMsg = jsonObj.error;
+                               } else {
+                                 var tenants = [];
+               for (var tenIndx = 0; tenIndx < jsonObj.items.length; tenIndx++) {
+                 tenants.push(jsonObj.items[tenIndx].name);
+               }
+               localStorageService.set('tenants', JSON.stringify(tenants));
+               $scope.ecdapp.availableTenants = tenants;        
+                               }                       
+                       }, function(error) {
+                               $log.error("executionsViewController.loadTable failed: " + error);
+                               $scope.ecdapp.isRequestFailed = true;
+                               $scope.ecdapp.errMsg = error;
+                       });
+         } else {
+           $scope.ecdapp.availableTenants = JSON.parse(tenantStr);
+    }
+         getActiveExecutions();
+               };
+
+       var getAppLabel = function() {
+    var label = localStorageService.get('appLabel');
+    if (!label) {
+      ControllerService.getAppLabel().then(function(jsonObj) {
+                       if (debug) {
+                               $log.debug("Controller.getAppLabel succeeded: " + JSON.stringify(jsonObj));
+                       }
+                       localStorageService.set('appLabel', JSON.stringify(jsonObj));
+                       $scope.ecdapp.appLabel = jsonObj;
+               }, function(error) {
+                       $log.error("Controller.getAppLabel failed: " + error);
+               });
+    } else {
+      $scope.ecdapp.appLabel = JSON.parse(label);
+    }
+       };
+  
+  var getBlueprintsCount = function() {
+    $scope.ecdapp.bpObjList = [];
+    $scope.ecdapp.currentBpId = '';
+    $scope.ecdapp.isBpDataLoading = true;
+    InventoryBlueprintService.getBlueprintIdsList($scope.ecdapp.searchByBp).then(
+        function(jsonObj) {
+          if (jsonObj.error) {
+            $log.error("execViewCtlr.getBlueprintsCount failed: "
+                + jsonObj.error);
+            $scope.ecdapp.bpCount = 0;
+            $scope.ecdapp.isBpDataLoading = false;
+            $scope.ecdapp.bpObjList = [];
+          } else {
+            $scope.ecdapp.bpCount = jsonObj.totalItems;
+            $scope.ecdapp.bpObjList = jsonObj.items;
+            $scope.ecdapp.isBpDataLoading = false;
+          }
+        },
+        function(error) {
+          $log.error("execViewCtlr.getBlueprintsCount failed: "
+              + error);
+          $scope.ecdapp.bpCount = 0;
+          $scope.ecdapp.bpObjList = [];
+          $scope.ecdapp.isBpDataLoading = false;
+        });
+  };
+  
+  $scope.ecdapp.updateDepl = function() {
+    $scope.ecdapp.currentDep = '';
+    if ($scope.ecdapp.currentBpId != '') {
+      $scope.ecdapp.isDeplDataLoading = true;
+      $scope.ecdapp.depObjList = [];
+      $scope.ecdapp.execData = [];
+      var srvcIds = [];
+      var srvcTypIds = [];
+      srvcTypIds.push($scope.ecdapp.currentBpId);
+      InventoryBlueprintService.getDeploymentForBp(srvcTypIds)
+      .then(function(jsonObj) {
+        if (jsonObj.error) {
+          $scope.ecdapp.depObjList = [];
+          $scope.ecdapp.isDeplDataLoading = false;
+        } else {
+          for (var typIndx = 0; typIndx < jsonObj.length; typIndx++) {
+            for (var depIndx = 0; depIndx < jsonObj[typIndx].serviceRefList.items.length; depIndx++) {
+              srvcIds.push(jsonObj[typIndx].serviceRefList.items[depIndx]);
+            }    
+          }
+          $scope.ecdapp.depObjList = srvcIds;
+          //$scope.ecdapp.currentDep = $scope.ecdapp.depObjList[0];
+          $scope.ecdapp.isDeplDataLoading = false;
+        }
+      }, function(error) {
+        $log.error("inventoryBlueprintController.updateTable failed: " + error);
+        bpDepls = [];
+        $scope.ecdapp.isDeplDataLoading = false;
+      });
+    }
+  };
+  $scope.ecdapp.copyStringToClipboard = function(str) {
+    // Create new element
+    var el = document.createElement('textarea');
+    // Set value (string to be copied)
+    el.value = str;
+    // Set non-editable to avoid focus and move outside of view
+    el.setAttribute('readonly', '');
+    el.style = {position: 'absolute', left: '-9999px'};
+    document.body.appendChild(el);
+    // Select text inside element
+    el.select();
+    // Copy text to clipboard
+    document.execCommand('copy');
+    // Remove temporary element
+    document.body.removeChild(el);
+ };
+
+  $scope.ecdapp.updateExec = function() {
+    if ($scope.ecdapp.currentDep != '') {
+      $scope.ecdapp.isExecDataLoading = true;
+      $scope.ecdapp.resetFilters();
+      var currentDeplId = $scope.ecdapp.currentDep.split(":")[0];
+      var currentDeplTenant = $scope.ecdapp.currentDep.split(":")[1];
+      InventoryExecutionService.getExecutionsByDeployment(currentDeplId, 
+          currentDeplTenant,
+          1,
+          1000).then(
+              function(jsonObj) {
+                if (jsonObj.error) {
+                  $scope.ecdapp.execData = [];
+                  $scope.ecdapp.isExecDataLoading = false;
+                } else {
+                  $scope.ecdapp.totalPages = jsonObj.totalPages;
+                  $scope.ecdapp.execData = jsonObj.items;
+                  $scope.ecdapp.isExecDataLoading = false;
+                }
+              }, function(error) {
+                $log.error("execViewCtlr.updateExec failed: " + error);
+                $scope.ecdapp.isExecDataLoading = false;
+              });
+    }
+  };
+
+  var getActiveExecutions = function() {
+    $scope.ecdapp.isExecDataLoading = true;
+    InventoryExecutionService.getActiveExecutions($scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage)
+        .then(
+            function(jsonObj) {
+              if (jsonObj.error) {
+                $scope.ecdapp.execData = [];
+                $scope.ecdapp.isExecDataLoading = false;
+              } else {
+                $scope.ecdapp.totalPages = jsonObj.totalPages;
+                $scope.ecdapp.execData = jsonObj.items;
+                $scope.ecdapp.isExecDataLoading = false;
+              }
+            }, function(error) {
+              $log.error("execViewCtlr.updateExec failed: " + error);
+              $scope.ecdapp.isExecDataLoading = false;
+            });
+  };
+  
+  var getPerTenantExecutions = function() {
+    $scope.ecdapp.isExecDataLoading = true;
+    InventoryExecutionService.getExecutionsByTenant($scope.ecdapp.selectedTenant,
+        $scope.ecdapp.selectedStatus, $scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage)
+        .then(
+            function(jsonObj) {
+              if (jsonObj.error) {
+                $scope.ecdapp.execData = [];
+                $scope.ecdapp.isExecDataLoading = false;
+              } else {
+                $scope.ecdapp.totalPages = jsonObj.totalPages;
+                $scope.ecdapp.execData = jsonObj.items;
+                $scope.ecdapp.isExecDataLoading = false;
+              }
+            }, function(error) {
+              $log.error("execViewCtlr.updateExec failed: " + error);
+              $scope.ecdapp.isExecDataLoading = false;
+            });
+  };
+  
+  var getExecutionForId = function() {
+    $scope.ecdapp.isExecDataLoading = true;
+    InventoryExecutionService.getExecutionsById($scope.ecdapp.execId, 
+        $scope.ecdapp.selectedTenant, $scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage)
+        .then(
+            function(jsonObj) {
+              if (jsonObj.error) {
+                $scope.ecdapp.execData = [];
+                $scope.ecdapp.isExecDataLoading = false;
+              } else {
+                $scope.ecdapp.totalPages = jsonObj.totalPages;
+                $scope.ecdapp.execData = jsonObj.items;
+                $scope.ecdapp.isExecDataLoading = false;
+              }
+            }, function(error) {
+              $log.error("execViewCtlr.getExecutionsById failed: " + error);
+              $scope.ecdapp.isExecDataLoading = false;
+            });
+  };
+  /**
+   * Invoked at first page load AND when
+   * user clicks on the B2B pagination control. 
+   */
+  $scope.pageChangeHandler = function(page) {
+    $scope.ecdapp.currentPage = page;
+    if ($scope.ecdapp.selectedTenant != '') {
+      getPerTenantExecutions();
+    }
+  }
+  
+  var getDeploymentsCount = function() {
+    $scope.ecdapp.isDepDataLoading = true;
+    $scope.ecdapp.execData = [];
+    InventoryDeploymentService.getDeploymentCount($scope.ecdapp.searchByDep).then(
+        function(jsonObj) {
+          if (jsonObj.error) {
+            $log.error("execViewCtlr.getDeploymentscount failed: "
+                + jsonObj.error);
+            $scope.ecdapp.depCount = 0;
+            $scope.ecdapp.depObjList = [];
+          } else {
+            $scope.ecdapp.depCount = jsonObj.totalItems;
+            $scope.ecdapp.depObjList = jsonObj.items;
+            $scope.ecdapp.isDepDataLoading = false;
+          }
+        },
+        function(error) {
+          $log.error("execViewCtlr.getDeploymentscount failed: "
+              + error);
+          $scope.ecdapp.isDepDataLoading = false;
+          $scope.ecdapp.depCount = 0;
+        });
+  }; 
+  
+  var getPluginsCount = function() {
+    $scope.ecdapp.isPluginDataLoading = true;
+    ControllerService.getPluginsCount().then(
+        function(jsonObj) {
+          if (jsonObj.error) {
+            $log.error("execViewCtlr.getPluginsCount failed: "
+                + jsonObj.error);
+            $scope.ecdapp.isPluginDataLoading = false;
+            $scope.ecdapp.pluginCount = 0;
+          } else {
+            $scope.ecdapp.pluginCount = jsonObj.totalItems;
+            $scope.ecdapp.isPluginDataLoading = false;
+          }
+        },
+        function(error) {
+          $log.error("execViewCtlr.getPluginsCount failed: "
+              + error);
+          $scope.ecdapp.pluginCount = 0;
+          $scope.ecdapp.isPluginDataLoading = false;
+        });
+  }; 
+  var getOwners = function() {
+    InventoryBlueprintService.getOwnersList().then(
+        function(jsonObj) {
+          if (jsonObj.error) {
+            $log.error("execViewCtlr.getOwnersList failed: "
+                + jsonObj.error);
+            $scope.ecdapp.bpOwners = [];
+          } else {
+            $scope.ecdapp.bpOwners = jsonObj;
+            localStorageService.set('bpOwners', JSON.stringify(jsonObj));
+          }
+        },
+        function(error) {
+          $log.error("execViewCtlr.getOwnersList failed: "
+              + error);
+          $scope.ecdapp.bpOwners = [];
+        });
+  };
+  
+       // Initialize the page
+       getTenants();
+       getAppLabel();
+       getBlueprintsCount();
+       getDeploymentsCount();
+       getOwners();
+       getPluginsCount();
+       getActiveExecutions();
+  $scope.$on('$destroy', function() {
+    $scope.ecdapp.stopLoading();
+  });
+});
diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions_view.html b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/executions_view.html
new file mode 100644 (file)
index 0000000..09d9814
--- /dev/null
@@ -0,0 +1,377 @@
+<div id="page-content">
+  <br>
+  <h4 class="heading-page" id="controllers">Dashboard</h4>
+  <hr class="lite">
+  <div class="span3 form-row btn-switch-label" style="margin-top: -60px;float: right;">
+      <div class="tooltip" b2b-tooltip trigger="focus">
+          <a  href="javascript:void(0)" class="tooltip-element"  data-placement="left" role="button"
+          style="text-decoration: none; margin-right: 10px;">
+              Access Type
+              <div class="arrow"></div>
+          </a>
+          <div class="tooltip-wrapper" role="tooltip" aria-live="polite" aria-atomic="false" style="z-index:1111">
+              <div class="tooltip-size-control">
+                  <div class="helpertext" tabindex="-1" role="tooltip" id="tooltiptext1">  
+                      <div class="popover-title">My Dashboard</div>  
+                      <div class="popover-content">
+                          <p>Toggle access type selection between logged in user's data or user role group data.</p>
+                          <strong class="hidden-spoken">Double tap to close help message.</strong>
+                      </div>
+                  </div>
+              </div>
+          </div>                           
+    </div>
+      <!--  <span aria-hidden="true">Access level</span>-->
+    <div b2b-switches-v2 id="switch1" style="margin-top: -5px;" ng-model="ecdapp.level_switch.value" options="ecdapp.level_options" ng-disabled="allDisabled" ng-change="ecdapp.toggleUserFilt()">
+    </div>
+  </div>
+  <div class="span3 form-row btn-switch-label">
+      <div class="tooltip" b2b-tooltip trigger="focus">
+          <a  href="javascript:void(0)" class="tooltip-element"  data-placement="left" role="button"
+          style="text-decoration: none; margin-right: 10px;">
+              Auto Refresh
+              <div class="arrow"></div>
+          </a>
+          <div class="tooltip-wrapper" role="tooltip" aria-live="polite" aria-atomic="false" style="z-index:1111">
+              <div class="tooltip-size-control">
+                  <div class="helpertext" tabindex="-1" role="tooltip" id="tooltiptext1">  
+                      <div class="popover-title">Reload data automatically</div>  
+                  </div>
+              </div>
+          </div>                           
+    </div>
+      <!--  <span aria-hidden="true">Access level</span>-->
+    <div b2b-switches-v2 id="switch2" ng-model="ecdapp.inv_load.value" options="ecdapp.inv_query_options" >
+    </div>
+  </div>
+  <button title="Expand/Collapse Tiles Container" class="collapsible"></button>
+  <div class="content">
+  <div class="b2b-card-container">
+    <div class="row">
+      <div class="span3 b2b-card-wid">
+        <div class="b2b-cards" style="border-radius: 8px;text-shadow: 1px 1px 7px #0574ac;border: 1px solid gray;border-top: 5px solid #0574ac;">
+          <div ng-show="ecdapp.isBpDataLoading" class="ng-scope ng-hide">
+            <div class="span" style="margin-bottom: 5px;">
+              <i class="icon-spinner small" role="img"></i>
+            </div>
+          </div>
+          <span class="tooltip" b2b-tooltip style="float: right; margin-top: -10px;">
+              <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" >
+                  <span class="arrow"></span>
+              </a>
+              <span class="tooltip-wrapper">
+                  <span class="tooltip-size-control">
+                      <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1">  
+                          <span class="popover-title">Aggregate count of blueprints for user/role set</span>  
+                          <span class="popover-content">
+                              <span>Navigation link to blueprints Inventory screen</span>
+                              <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong>
+                          </span>
+                      </span>
+                  </span>
+              </span>
+          </span>
+          <a ng-if="ecdapp.level_switch.value" href="ecd#/ibp/owner:{{userId}}">
+            <div class="b2b-card-header">
+              <i class="icon-documents-document" role="img" style="font-size: 35px;margin-top: -20px;margin-left: -20px;"></i>
+              <span class="b2b-title" > {{ecdapp.bpCount}} </span>
+            </div>
+            <div class="b2b-card-content"
+              style="text-align: center;">
+              BLUEPRINTS            
+            </div>
+          </a>
+          <a ng-if="!ecdapp.level_switch.value" href="ecd#/ibp/owner:group">
+            <div class="b2b-card-header">
+              <i class="icon-documents-document" role="img" style="margin-top: -20px; 
+              margin-left: -20px; font-size: 35px"></i>
+              <span class="b2b-title" > {{ecdapp.bpCount}} </span>
+            </div>
+            <div class="b2b-card-content"
+              style="text-align: center;">
+              BLUEPRINTS            
+            </div>
+          </a>
+        </div>
+      </div>
+      <div class="span3 b2b-card-wid">
+        <div class="b2b-cards" style="text-shadow: 1px 1px 7px #008744;border-radius:8px;border: 1px solid gray;border-top: 5px solid #008744;">
+          <div ng-show="ecdapp.isDepDataLoading" class="ng-scope ng-hide">
+            <div class="span" style="margin-bottom: 5px;">
+              <i class="icon-spinner small" role="img"></i>
+            </div>
+          </div>
+                    <span class="tooltip" b2b-tooltip style="float: right; margin-top: -10px;">
+              <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" >
+                  <span class="arrow"></span>
+              </a>
+              <span class="tooltip-wrapper">
+                  <span class="tooltip-size-control">
+                      <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1">  
+                          <span class="popover-title">Aggregate count of deployments for user/role set</span>  
+                          <span class="popover-content">
+                              <span>Navigation link to cloudify deployments Inventory screen</span>
+                              <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong>
+                          </span>
+                      </span>
+                  </span>
+              </span>
+          </span>
+          <a ng-if="ecdapp.level_switch.value" href="ecd#/idep/owner:{{userId}}">
+            <div class="b2b-card-header">
+              <i class="icon-misc-business" role="img" style="margin-top: -20px; 
+              margin-left: -20px; font-size: 35px"></i>
+              <span class="b2b-title"> {{ecdapp.depCount}} </span>
+            </div>
+            <div class="b2b-card-content"
+              style="text-align: center;">
+              DEPLOYMENTS
+            </div>
+          </a>
+          <a ng-if="!ecdapp.level_switch.value" href="ecd#/idep/owner:group">
+            <div class="b2b-card-header">
+              <i class="icon-misc-business" role="img" style="font-size: 35px;margin-top: -20px;margin-left: -20px;"></i>
+              <span class="b2b-title"> {{ecdapp.depCount}} </span>
+            </div>
+            <div class="b2b-card-content"
+              style="text-align: center;">
+              DEPLOYMENTS
+            </div>                     
+          </a>                   
+        </div>
+      </div>
+      <div class="span3 b2b-card-wid">
+        <div class="b2b-cards" style="text-shadow: 1px 1px 7px #e7d81e;border-radius:8px;border: 1px solid gray;border-top: 5px solid #e7d81e;">
+          <div ng-show="ecdapp.isPluginDataLoading" class="ng-scope ng-hide">
+            <div class="span" style="margin-bottom: 5px;">
+              <i class="icon-spinner small" role="img"></i>
+            </div>
+          </div>
+                    <span class="tooltip" b2b-tooltip style="float: right; margin-top: -10px;">
+              <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" >
+                  <span class="arrow"></span>
+              </a>
+              <span class="tooltip-wrapper">
+                  <span class="tooltip-size-control">
+                      <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1">  
+                          <span class="popover-title">Aggregate count of cloudify plugins</span>  
+                          <span class="popover-content">
+                              <span>Navigation link to cloudify plugins screen</span>
+                              <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong>
+                          </span>
+                      </span>
+                  </span>
+              </span>
+          </span>
+          <a href="ecd#/iplug">
+            <div class="b2b-card-header">
+              <i class="icon-controls-gear" role="img" style="font-size: 35px;margin-top: -20px;margin-left: -20px;"></i>
+              <span class="b2b-title"> {{ecdapp.pluginCount}} </span>
+            </div>
+            <div class="b2b-card-content"
+              style="text-align: center;">
+              PLUGINS
+            </div>
+          </a>                  
+        </div>
+      </div>
+    </div>
+  </div>
+  <div class="span9 row-nowrap" style="margin-bottom: 10px; float: right; margin-top: -30px;">
+    <div class="span6 form-row">
+      <div class="span12 field-group">
+      <input class="span12" list="bpList" type="input" ng-model="ecdapp.currentBpId" ng-change="ecdapp.updateDepl()" placeholder="Blueprints"/>
+      <span class="tooltip" style="float: right; margin-top: -30px;" b2b-tooltip>
+          <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" >
+              <span class="arrow"></span>
+          </a>
+          <span class="tooltip-wrapper">
+              <span class="tooltip-size-control">
+                  <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1">  
+                      <span class="popover-title">Blueprints list</span>  
+                      <span class="popover-content">
+                          <span>autocomplete dropdown list of blueprints, a selection will trigger deployment list query</span>
+                          <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong>
+                      </span>
+                  </span>
+              </span>
+          </span>
+      </span>
+      <datalist id="bpList">
+        <option ng-repeat="d in ecdapp.bpObjList" value="{{d.typeId}}">{{d.typeName}}</option>
+      </datalist>
+      </div>
+    </div>
+    <div class="span1 form-row">
+        <div ng-show="ecdapp.isDeplDataLoading" class="ng-scope ng-hide">
+          <div class="span" style="margin-bottom: 5px;">
+            <i class="icon-spinner small" role="img"></i>
+          </div>
+        </div>
+    </div>
+    <div class="span6 form-row">
+      <!--  <label for="depl">Deployments</label>-->
+
+      <div class="span12 field-group">
+      <input id="depInput" class="span12" list="depList" type="input" ng-model="ecdapp.currentDep" ng-change="ecdapp.updateExec()" placeholder="Deployments"/>
+      <span class="tooltip" style="float: right; margin-top: -30px;" b2b-tooltip>
+              <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" >
+                  <span class="arrow"></span>
+              </a>
+              <span class="tooltip-wrapper">
+                  <span class="tooltip-size-control">
+                      <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1">  
+                          <span class="popover-title">Deployments list</span>  
+                          <span class="popover-content">
+                              <span>autocomplete dropdown list of deployments, a selection will trigger deployment executions query</span>
+                              <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong>
+                          </span>
+                      </span>
+                  </span>
+              </span>
+          </span>
+      <datalist id="depList">
+        <option ng-repeat="d in ecdapp.depObjList" value="{{d.id}}:{{d.tenant_name}}">{{d.id}}</option>
+      </datalist>
+      </div>
+    </div>
+  </div>
+  </div>
+  <div ng-hide="ecdapp.errMsg"  style="margin-top: 40px;border: 1px solid gray;border-radius: 5px;padding: 10px;clear: both;border-top: 2px solid #0d2dca;">
+    <label for="executions-table">Executions</label>
+              <span class="tooltip" b2b-tooltip style="float: right; margin-top: -10px;">
+              <a href="#" class="icon-tooltip tooltip-element" tabindex="0" role="button" data-placement="bottom" aria-label="Help" aria-describedby="tooltiptextRadio" >
+                  <span class="arrow"></span>
+              </a>
+              <span class="tooltip-wrapper">
+                  <span class="tooltip-size-control">
+                      <span id="tooltiptextRadio" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1">  
+                          <span class="popover-title">Executions summary table</span>  
+                          <span class="popover-content">
+                              <span>Current active executions are displayed by default. Use the search box to specify additional query filters for deployment executions. A deployment selection will automatically trigger a refresh of the executions table.</span>
+                              <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong>
+                          </span>
+                      </span>
+                  </span>
+              </span>
+          </span>
+    <div id="button-search-row" style="float: right;width: 50%;">
+        <div class="advanced-search">
+          <input tabindex="0" style="padding-left: 50px;"
+            placeholder="Enter search filters from the dropdown menu"
+            class="advanced-search-input" type="text"></input>
+          <button type="button" id="show-menu-filters"
+            class="btn dropdown-toggle"
+            ng-click="ecdapp.toggleMoreFilters()" data-toggle="dropdown"
+            title="More Filters">
+            <i class="icon-controls-down"></i>
+          </button>
+        </div>
+        <div class="menu-filters" ng-show="ecdapp.showingMoreFilters" style="width: 40%;">
+          <div class="group">
+            <label class="col-sm-3 control-label">Execution ID: </label> <input
+              tabindex="0" class="advanced-search-input" type="text"
+              title="Search by execution ID"
+              ng-model="ecdapp.execId"></input>
+          </div>
+          <div class="group">
+            <label class="col-sm-3 control-label">Tenants: </label>
+              <div class="field-group">
+                <select class="span12" name="tenant" b2b-dropdown placeholder-text="Select Tenant" ng-model="ecdapp.selectedTenant">
+                <option b2b-dropdown-list option-repeat="d in ecdapp.availableTenants" value="{{d}}">{{d}}</option>
+                </select>
+              </div>
+          </div>
+          <div class="group">
+            <label class="col-sm-3 control-label">Status: </label>
+              <div class="field-group">
+                <select class="span12" name="status" b2b-dropdown placeholder-text="Select status" ng-model="ecdapp.selectedStatus">
+                <option b2b-dropdown-list option-repeat="d in ecdapp.availableStatus" value="{{d}}">{{d}}</option>
+                </select>
+              </div>
+          </div>
+          <div class="group" style="float: right;">
+            <button tabindex="-1" class="btn btn-small"
+              title="Reset Filters" type="button"
+              ng-click="ecdapp.resetFilters()">
+              <i class="icon-arrows-update-refresh-sync"></i>
+            </button>
+            <button tabindex="1" class="btn btn-small"
+              title="Filtered search" type="button"
+              ng-click="ecdapp.extendedfilterSrch()">
+              <i class="icon-controls-magnifyingglass"></i>
+            </button>
+          </div>
+        </div>
+    </div>
+    <hr class="lite" style="margin-top: 20px;">
+    <div ng-show="ecdapp.isExecDataLoading" class="ng-scope ng-hide">
+      <div class="span" style="margin-bottom: 5px;">
+        <i class="icon-spinner small" role="img"></i>
+      </div>
+    </div>
+    <div b2b-table id="executions-table" class="b2b-table-div"
+      table-data="ecdapp.execData" search-string="ecdapp.searchString"
+      current-page="ecdapp.currentPageIgnored"
+      next-sort="ecdapp.nextSortIgnored">
+      <table>
+        <thead b2b-table-row type="header">
+          <tr id="th-header-row">
+            <th b2b-table-header key="index"></th>
+            <th b2b-table-header key="deployment_id">Deployment</th>
+            <th b2b-table-header key="workflow_id">Workflow</th>
+            <th b2b-table-header key="created_at">Created</th>
+            <th b2b-table-header key="ended_at">Ended</th>          
+            <th b2b-table-header key="tenant_name">Tenant</th>
+            <th b2b-table-header key="status">Status</th>
+          </tr>
+        </thead>
+        <tbody b2b-table-row type="body"
+          ng-repeat="rowData in ecdapp.execData">
+          <tr id="tr-rowData">
+            <td b2b-table-body>
+              <div class="id-tooltip"><span>ID</span>
+                <div class="wrapper">
+                    <button style="border-radius: 5px;margin-right: 20px;font-weight: lighter;border: 1px solid black;" 
+                    ng-click="ecdapp.copyStringToClipboard(rowData.id)" class="">Copy ID</button>
+                  <span class="id-tooltiptext">{{rowData.id}}</span>
+                </div>
+              </div>
+            </td>
+            <!--  <td b2b-table-body>ID</td>-->
+            <td b2b-table-body>
+             <a href="ecd#/idep/tenant:{{rowData.tenant_name}};serviceRef:{{rowData.deployment_id}}">
+                      {{rowData.deployment_id}}
+             </a>
+            </td>
+            <td b2b-table-body ng-bind="rowData.workflow_id" />
+            <td b2b-table-body ng-bind="rowData.created_at" />
+            <td b2b-table-body ng-bind="rowData.ended_at" />
+            <td b2b-table-body ng-bind="rowData.tenant_name" />
+            <!--  <td b2b-table-body ng-bind="rowData.id" />-->
+            <td b2b-table-body ng-if="rowData.status == 'pending'" >
+              <span class="ng-scope" style="background-color: #edef8e;padding: 5px;border-radius: 3px; opacity: 0.6; font-weight: bold;">waiting to start</span></td>
+            <td b2b-table-body ng-if="rowData.status == 'started'" >
+              <span class="ng-scope" style="background-color: ##f0fd2e;padding: 5px;border-radius: 3px; opacity: 0.6; font-weight: bold;">in-progress</span></td>
+            <td b2b-table-body ng-if="rowData.status == 'cancelling'" >
+              <span class="ng-scope" style="background-color: #cabdbd;padding: 5px;border-radius: 3px;opacity: 0.6; font-weight: bold;">cancel in progress</span></td>
+            <td b2b-table-body ng-if="rowData.status == 'force_cancelling'" >
+              <span class="ng-scope" style="background-color: #cabdbd;padding: 5px;border-radius: 3px;opacity: 0.6; font-weight: bold;"">force-cancelling in progress</span> </td>
+            <td b2b-table-body ng-if="rowData.status == 'cancelled'" >
+              <span class="ng-scope" style="background-color: #9a9690;padding: 5px;border-radius: 3px;opacity: 0.6; font-weight: bold;">cancelled</span>
+            </td>
+            <td b2b-table-body ng-if="rowData.status == 'terminated'" >
+              <span class="ng-scope" style="background-color: #62d826;padding: 5px;border-radius: 3px;opacity: 0.6; font-weight: bold;">successful</span>
+            </td>
+            <td b2b-table-body ng-if="rowData.status == 'failed'">
+              <span class="ng-scope" style="background-color: #fd2e2e;padding: 5px;border-radius: 3px;opacity: 0.6; font-weight: bold;">failed</span>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+    <div b2b-pagination="" total-pages="ecdapp.totalPages"
+      current-page="ecdapp.currentPageNum"
+      click-handler="pageChangeHandler" role="navigation"></div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/home/oom-style.css b/ccsdk-app-os/src/main/webapp/app/ccsdk/home/oom-style.css
new file mode 100644 (file)
index 0000000..df3e489
--- /dev/null
@@ -0,0 +1,658 @@
+/* Styles for ECOMP Controller Dashboard */
+
+.content-container {
+       min-height: 650px;
+       width: calc(100% - 50px);
+}
+
+.ecd-error-message {
+       font-size: 14px;
+       font-weight: bold;
+       color: red;
+}
+
+.ecd-icon-display {
+       font-size: 18px;
+}
+
+.ecd-icon-action {
+       font-size: 18px;
+}
+
+.ecd-icon-action:hover {
+       color: red;
+       text-decoration: none;
+}
+
+.selected {
+    background-color:#abb5e6;
+    color:black;
+    font-weight:bold;
+}
+.red-background {
+   background-color: #ff0000b3;
+ }
+.green-background {
+   background-color: #bbf0bb;
+ } 
+.td-error {
+    border-top: 2px dotted red;
+    border-bottom: 2px dotted red;
+    background-color: rgb(210, 190, 190);
+ }
+.menu {
+       display: none;
+       z-index: 1000;
+       border: 1px dotted;
+       border-radius: 5px;
+       padding: 10px;
+       width: 40%;
+       background: azure;
+       position: fixed;
+       overflow: scroll;
+        background: slategray;
+        color: white;
+        right: 20px;
+}
+
+.show-menu {
+       z-index: 800;
+}
+
+#show-menu {
+       display: none;
+}
+
+#show-menu:checked ~ .menu {
+       display: block;
+}
+
+#show-menu:checked ~ .show-menu {
+       color: blue;
+}
+
+.menu-off {
+       position: fixed;
+       left: 0;
+       right: 0;
+       top: 0;
+       bottom: 0;
+       z-index: 700;
+       display: none;
+}
+
+.menu-off {
+       display: none;
+}
+
+#show-menu:checked ~ .menu-off {
+       display: block;
+}
+
+#show-menu:checked ~ .show-menu {
+       display: none;
+}
+
+.menu-off input[type=checkbox]:checked ~ .menu {
+       display: none;
+}
+
+.menu-off input[type=checkbox]:checked ~ .show-menu {
+       display: block;
+}
+
+.menu-filters {
+       display: block;
+       z-index: 1000;
+       border: 1px dotted;
+       border-radius: 5px;
+       padding: 10px;
+       width: 48%;
+       background: #ffffff;
+       position: absolute;
+       overflow: scroll;
+}
+
+.show-menu-filters {
+       z-index: 800;
+       color: blue;
+}
+
+#show-menu-filters[aria-expanded="true"] ~ .menu-filters {
+       display: block;
+}
+
+#show-menu-filters:checked ~ .show-menu-filters {
+       color: blue;
+}
+
+.menu-filters-off {
+       position: fixed;
+       left: 0;
+       right: 0;
+       top: 0;
+       bottom: 0;
+       z-index: 700;
+       display: none;
+}
+
+.menu-filters-off {
+       display: none;
+}
+
+#show-menu-filters:checked ~ .menu-filters-off {
+       display: block;
+}
+
+#show-menu-filters:checked ~ .show-menu-filters {
+       display: none;
+}
+
+.menu-filters-off input[type=checkbox]:checked ~ .menu-filters {
+       display: none;
+}
+
+.menu-filters-off input[type=checkbox]:checked ~ .show-menu-filters {
+       display: block;
+}
+
+.ui-select-match .btn {
+       font-size: 1.5rem;
+       padding: 5px;
+}
+
+.ui-select-multiple.ui-select-bootstrap .ui-select-match .close {
+       font-size: 1.0em;
+       margin-left: 10px;
+}
+.advanced-search {
+       display: block;
+       position: relative;
+}
+
+.advanced-search .btn{
+       box-shadow: none;
+       position: absolute;
+       top: 5px;
+       right: 3px;
+       min-width: 10px;
+       width: 25px;
+       height: 25px;
+       padding: 1px 1px 1px 1px;
+       
+}
+
+.advanced-search i {
+       position: relative;
+       top: 0px;
+       right: 0px;
+       width: 20px;
+       height: 20px;
+       padding: 0px 0px 0px 0px;
+       margin: 0px 0px 0px 0px;
+}
+
+.advanced-search-input {
+    padding: 10px 19px 9px 18px;
+    font-size: 1.5rem;
+    border-radius: 8px;
+    width: 100%;
+}
+td > .btn-group {
+       min-width: 0;
+       width: auto;
+}
+
+.dropup,
+.dropdown {
+  position: relative;
+}
+.dropdown-toggle:focus {
+  outline: 0;
+}
+.dropdown-menu {
+  position: absolute;
+  z-index: 1000;
+  display: none;
+  min-width: 160px;
+  padding: 5px 0;
+  margin: 2px 0 0;
+  text-align: left;
+  list-style: none;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, .15);
+  border-radius: 4px;
+  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+          box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+  top: 30px;
+  left: -10px;
+}
+.dropdown-menu.pull-right {
+  right: 0;
+  left: auto;
+}
+.dropdown-menu .divider {
+  height: 1px;
+  margin: 9px 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+.dropdown-menu > li > a {
+  display: block;
+  padding: 3px 20px;
+  clear: both;
+  font-weight: normal;
+  line-height: 1.42857143;
+  color: #333;
+  white-space: nowrap;
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  color: #262626;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  color: #fff;
+  text-decoration: none;
+  background-color: #337ab7;
+  outline: 0;
+}
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  color: #777;
+}
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+  background-image: none;
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+}
+.open > .dropdown-menu {
+  display: block;
+}
+.open > a {
+  outline: 0;
+}
+.dropdown-menu-right {
+  right: 0;
+  left: auto;
+}
+.dropdown-menu-left {
+  right: auto;
+  left: 0;
+}
+.dropdown-header {
+  display: block;
+  padding: 3px 20px;
+  font-size: 12px;
+  line-height: 1.42857143;
+  color: #777;
+  white-space: nowrap;
+}
+.dropdown-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 990;
+}
+.pull-right > .dropdown-menu {
+  right: 0;
+  left: auto;
+}
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+  content: "";
+  border-top: 0;
+  border-bottom: 4px dashed;
+  border-bottom: 4px solid \9;
+}
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-bottom: 2px;
+}
+@media (min-width: 768px) {
+  .navbar-right .dropdown-menu {
+    right: 0;
+    left: auto;
+  }
+  .navbar-right .dropdown-menu-left {
+    right: auto;
+    left: 0;
+  }
+}
+
+.dropdown-menu li {
+       margin-bottom: 5px;
+}
+
+.dropdown-menu li div {
+       padding-left: 5px;
+}
+
+.dropdown-menu li div i {
+       margin-right: 5px;
+}
+
+td > .btn-group > .btn {
+       min-width: 0;
+       color: #0568ae;
+}
+
+td > .btn-group > .btn> i {
+       font-size: 30px;
+}
+
+li > a.active {
+       font-weight: bolder;
+       outline: thin dotted #666;
+}
+
+tr:hover {
+       background-color: #f2f2f2;
+}
+
+tr:focus {
+       background-color: #f2f2f2;
+}
+
+.modalwrapper.modal-docked .modal-jumbo {
+    max-height: 100%;
+    height: 100%;
+    overflow: hidden;
+    top: 0;
+    width: 100%;
+    max-width: 100%;
+}
+
+#addAppDiv {
+       padding-left: 10px;
+    background: lightgray;
+    border-radius: 5px;
+    padding-bottom: 15px;
+}
+
+.field-group.error .error-msg {
+       color: red;
+    display: block;
+    font-size: 14px;
+    line-height: 14px;
+    font-family: "Omnes-ATT-W02-Medium";
+    position: relative;
+    padding-left: 18px;
+    margin-top: 10px;
+}
+
+.heading-page {
+       margin-bottom: 20px;
+}
+
+.footer-container {
+       top: 25px;
+}
+.b2b-dragdrop {
+       padding: 10px;
+}
+
+.my-tooltip {
+  position: relative;
+  display: inline;
+}
+
+.id-tooltip {
+  position: relative;
+  display: inline;
+}
+
+.id-tooltip > .id-tooltiptext, .id-tooltip > .wrapper {
+       display: flex;
+    visibility: hidden;
+    width: 400px;
+    background-color: #dbdde3;
+    white-space: pre-line;
+    border-radius: 6px;
+    padding: 10px;
+    position: absolute;
+    bottom: 25%;
+    left: 80%;
+    transition: opacity 0.3s;
+    border: 1px solid gray;
+}
+
+.id-tooltip:hover > .id-tooltiptext, .id-tooltip:hover > .wrapper {
+  pointer-events: auto;
+  visibility: visible;
+  opacity: 1;
+}
+.wrapper > .id-tooltiptext {
+    overflow-y: auto;
+    max-height: 400px;
+    display: block;
+    clear: both;
+} 
+
+.id-tooltip .id-tooltiptext::after {
+  content: "";
+  position: absolute;
+  top: 40%;
+  right: 100%; 
+  margin-left: -5px;
+  border-width: 5px;
+  border-style: solid;
+  border-color: transparent #544f4f transparent transparent;
+}
+
+.wrapper {
+    position:relative;
+}
+
+.my-tooltip > .my-tooltiptext, .my-tooltip > .wrapper {
+       visibility: hidden;
+       width: 600px;
+       background-color: #647dd6;
+       color: #fff;
+       white-space: pre-line;
+       border-radius: 6px;
+       padding: 10px;
+       position: absolute;
+       z-index: 1;
+       bottom: 90%;
+       left: -5%;
+       opacity: 0;
+       transition: opacity 0.3s;
+       overflow: visible;
+}
+
+.my-tooltip .my-tooltiptext::after {
+  content: "";
+  position: absolute;
+  top: 100%;
+  left: 50%;
+  margin-left: -5px;
+  border-width: 5px;
+  border-style: solid;
+  border-color: #555 transparent transparent transparent;
+}
+
+.my-tooltip:hover > .my-tooltiptext, .my-tooltip:hover > .wrapper {
+  pointer-events: auto;
+  visibility: visible;
+  opacity: 1;
+}
+.wrapper > .my-tooltiptext {
+    overflow-y: auto;
+    max-height: 400px;
+    display: block;
+    clear: both;
+} 
+
+.stat_tooltip {
+  position: relative;
+  display: inline-block;
+  top: -10px;
+}
+
+.gen_tooltip {
+       display: inline-block;
+       position: relative;
+}
+
+.gen_tooltip .gen_tooltiptext_r {
+    visibility: hidden;
+    width: 250px;
+    background-color: #647dd6;
+    color: #000;
+    text-align: center;
+    border-radius: 2px;
+    border: 1px solid rgba(0, 0, 0, .15);
+    padding: 5px 0;
+    position: absolute;
+    z-index: 100;
+    left: 110%;
+    top: -50%; 
+}
+
+.gen_tooltip .gen_tooltiptext_r::after {
+  content: "";
+  position: absolute;
+  top: 50%;
+  right: 100%; /* to the left of tooltip */
+  margin-left: -5px;
+  border-width: 5px;
+  border-style: solid;
+  border-color: transparent #fff transparent transparent;
+}
+
+.gen_tooltip:hover .gen_tooltiptext_r {
+  visibility: visible;
+}
+
+.stat_tooltip .stat_tooltiptext, .stat_tooltip .wrapper {
+    visibility: hidden;
+    width: 500px;
+    background-color: #c8d1f0;
+    color: #000;
+    text-align: left;
+    border-radius: 6px;
+    border: 1px solid rgba(0, 0, 0, .15);
+    padding: 5px 0;
+    position: absolute;
+    z-index: 100;
+    bottom: 100%;
+    height: 200px;
+}
+
+.stat_tooltip .stat_tooltiptext::after, .stat_tooltip .wrapper::after {
+  content: "";
+  position: absolute;
+  top: 100%;
+  left: 4%;
+  margin-left: -5px;
+  border-width: 5px;
+  border-style: solid;
+  border-color: rgba(0, 0, 0, .15) transparent transparent transparent;
+}
+
+.stat_tooltip:hover .stat_tooltiptext, .stat_tooltip:hover .wrapper {
+  visibility: visible;
+}
+
+.stat_tooltip .wrapper .clip-btn-div {
+    display: inline;
+    left: 50px;
+    top: 80px;
+}
+
+.b2b-card-container {
+       background-color: #ffffff; 
+}
+
+.b2b-cards {
+       transition: .5s;
+       opacity: .7;
+}
+.b2b-cards a {
+       text-decoration: none;  
+}
+
+.b2b-cards:hover {
+  box-shadow: 0px 0px 20px 10px #eccc5e;
+  text-shadow: none !important;
+  background-color: #ffffff !important;
+  opacity: 1;
+  
+}
+
+.b2b-cards .tooltip {
+       visibility: hidden;
+}
+
+.b2b-cards:hover .tooltip {
+       visibility: visible;
+}
+
+.b2b-cards .b2b-card-footer-flyout {
+       visibility: hidden;
+}
+
+.b2b-cards:hover .b2b-card-footer-flyout {
+       visibility: visible;
+}
+.b2b-card-header {
+    text-align: center;
+}
+
+.b2b-card-header i {
+       font-size: 35px;
+}
+.b2b-card-container .b2b-title {
+       font-size: 50px;
+}
+.b2b-card-content {
+       text-align: center;
+}
+
+.collapsible {
+    color: #2196F3;
+    cursor: pointer;
+    padding: 18px;
+    width: 100%;
+    border: none;
+    outline: none;
+    font-size: 25px;
+    font-weight: bolder;
+    background-color: #ffffff;
+    height: 2px;
+    margin-top: -30px;
+}
+
+.collapsible:after {
+  content: "\2796";
+  color: #2196F3;
+  float: right;
+  margin-left: 5px;
+}
+
+.collapsible.active:after {
+  content: '\02795';
+}
+
+.content {
+  padding: 0 18px;
+  height: auto;
+  display: block;
+  transition: max-height 0.2s ease-out;
+
+}
        <script src="app/fusion/external/angular-1.4.13/angular-sanitize.js"></script>  
        <script src="app/fusion/external/angular-1.4.13/angular-touch.js"></script>
        <script src="app/fusion/external/jquery/dist/jquery.min.js"></script>
-       <!--<script src="app/fusion/external/javascript-detect-element-resize/jquery.resize.js"></script>-->
        <script src="app/fusion/external/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
        
        <!-- Third-party scripts from app -->
-       <!-- https://github.com/jeremyfa/yaml.js -->
        <script src="app/ccsdk/external/bootstrap.min.js" type="text/javascript"></script>
        <script src="app/ccsdk/external/yaml.js" type="text/javascript"></script>
-       
+       <script src="app/ccsdk/external/index.js" type="text/javascript"></script>
+       <script src="app/ccsdk/external/select.js" type="text/javascript"></script>
+    <script src="app/ccsdk/external/angular-local-storage.js" type="text/javascript"></script>
        <script src="app/fusion/external/b2b/js/b2b-angular/b2b-library.js"></script>
+  
        <!-- Tweaked CSS -->
        <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/b2b-angular.css">
        <link rel="stylesheet" type="text/css" href="app/fusion/external/b2b/css/b2b-angular/font_icons.css">
@@ -54,7 +55,9 @@
        <link rel="stylesheet" type="text/css" href="app/fusion/external/ds2/css/digital-ng-library/ecomp-ionicons.css">
 
        <link rel="stylesheet" type="text/css" href="app/fusion/styles/ecomp.css">
-       
+       <link rel="stylesheet" type="text/css" href="app/ccsdk/external/select.css">
+    <link rel="stylesheet" href="app/ccsdk/home/oom-style.css"/>  
+    
     <!-- main app -->
        <script src="app/ccsdk/home/modal-service.js"></script>
        <script src="app/ccsdk/home/appDS2.js"></script> 
        <script src="app/ccsdk/home/controller-service.js"></script>
     <script src="app/ccsdk/home/executions-view-controller.js"></script>
        <script src="app/ccsdk/home/api-docs-controller.js"></script>
-       <!--  
-       <script src="app/ccsdk/home/tree-view-controller.js"></script>
-       <script src="app/ccsdk/home/tree-view-directive.js"></script>
-       <script src="app/ccsdk/home/oom-instances-controller.js"></script>
-       <script src="app/ccsdk/home/http-interceptor.js"></script>
-       -->
-       <link rel="stylesheet" href="app/ccsdk/home/tree-view-style.css"/>
-       <link rel="stylesheet" href="app/ccsdk/home/oom-style.css"/>    
 
        <!-- Cloudify -->
-       <script src="app/ccsdk/cloudify/blueprint-service.js"></script>
        <script src="app/ccsdk/cloudify/deployment-service.js"></script>
-       <script src="app/ccsdk/cloudify/execution-service.js"></script>
-       <script src="app/ccsdk/cloudify/tosca-table-controller.js"></script>
-       <script src="app/ccsdk/cloudify/blueprint-controllers.js"></script>
        <script src="app/ccsdk/cloudify/deployment-controllers.js"></script>
-       <script src="app/ccsdk/cloudify/execution-table-controller.js"></script>
-       
+    <script src="app/ccsdk/cloudify/execution-service.js"></script>
+       <script src="app/ccsdk/cloudify/plugin-table-controller.js"></script>
+    <script src="app/ccsdk/cloudify/plugin-service.js"></script>
+    
        <!--Inventory-->
        <script src="app/ccsdk/inventory/blueprint-service.js"></script>
-       <script src="app/ccsdk/inventory/deployment-service.js"></script>
-       <script src="app/ccsdk/inventory/execution-service.js"></script>
        <script src="app/ccsdk/inventory/blueprint-controllers.js"></script>
-       <script src="app/ccsdk/inventory/deployment-controllers.js"></script>
-       
+       <script src="app/ccsdk/inventory/deployment-service.js"></script>
+    <script src="app/ccsdk/inventory/execution-service.js"></script>
+  
        <!-- Consul -->
        <script src="app/ccsdk/consul/service-health-service.js"></script>      
        <script src="app/ccsdk/consul/service-controllers.js"></script>
        <script src="app/ccsdk/consul/node-services-controller.js"></script>
        <script src="app/ccsdk/consul/datacenter-table-controller.js"></script>
        <script src="app/ccsdk/consul/datacenter-health-service.js"></script>
-
-       <!-- Ops -->
-       <script src="app/ccsdk/ops/tabs-view-controller.js"></script>
        
        <!-- user admin pages --> 
        <script src="app/fusion/scripts/DS2-services/adminService.js"></script>
        <script src="app/fusion/scripts/DS2-controllers/fn-menu-add-popup-controller.js"></script>
        
        <!-- main page -->
-       <script src="app/ccsdk/home/oom-router.js"></script>
+       <script src="app/ccsdk/home/app-router.js"></script>
 
        <style>
                .csep-root1{
        </head>
        <body class="appBody" ng-app="abs">
                <!-- double quotation marks are required for the popup templates - values are string literals -->
-               <div ng-include src="'app/ccsdk/home/oom_popup_templates.html'"></div>
-               <div ng-include src="'app/ccsdk/home/oom_instances_popup.html'"></div>
-               <div ng-include src="'app/ccsdk/cloudify/blueprint_popups.html'"></div>
+               <div ng-include src="'app/ccsdk/home/ecd_popup_templates.html'"></div>
                <div ng-include src="'app/ccsdk/cloudify/deployment_popups.html'"></div>
                <div ng-include src="'app/ccsdk/inventory/inventory_blueprint_popups.html'"></div>
-               <div ng-include src="'app/ccsdk/inventory/inventory_deployment_popups.html'"></div>
-               <div ng-include src="'app/ccsdk/inventory/inventory_execution_popups.html'"></div>
-           <div ng-include src="'app/ccsdk/consul/service_popups.html'"></div>
+           <div ng-include src="'app/ccsdk/inventory/inventory_execution_popups.html'"></div>  
+        <div ng-include src="'app/ccsdk/inventory/inventory_deployment_popups.html'"></div> 
+        <div ng-include src="'app/ccsdk/consul/service_popups.html'"></div>
            <div ng-include src="'app/ccsdk/consul/node_popups.html'"></div>
                <div ds2-header id="header" class="header-container"></div>
                <div ds2-menu id="menu-container" class="menu-container"></div>
diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/images/ecomp.png b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/ecomp.png
new file mode 100644 (file)
index 0000000..b355f10
Binary files /dev/null and b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/ecomp.png differ
diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_16x16.ico b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_16x16.ico
new file mode 100644 (file)
index 0000000..8eb0495
Binary files /dev/null and b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_16x16.ico differ
diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_32x32.ico b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_32x32.ico
new file mode 100644 (file)
index 0000000..e434286
Binary files /dev/null and b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_32x32.ico differ
diff --git a/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_logo_2257x496.png b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_logo_2257x496.png
new file mode 100644 (file)
index 0000000..36ee1f5
Binary files /dev/null and b/ccsdk-app-os/src/main/webapp/app/ccsdk/images/onap_logo_2257x496.png differ
index 8a27586..88bab24 100644 (file)
@@ -56,7 +56,7 @@
 .icon-misc-trash:before, 
 .icon-misc-pen:before,
 .ion-navicon:before, 
-.icon-primary-close:before, .close:before, .reset-field:before,
+.icon-primary-close:before, .reset-field:before,
 .icon-datanetwork-softwareasaservice:before,
 .icon-datanetwork-messaging2:before,
 .icon-controls-settingsconnectedactivity:before,
 
 .icon-content-star:before { content: "\f24e"; }
 
-.icon-primary-close:before, .close:before, .reset-field:before { content: "\f129"; }
+.icon-primary-close:before, .reset-field:before { content: "\f129"; }
 
 .icon-datanetwork-softwareasaservice:before { content: "\f40c"; }
 
diff --git a/ccsdk-app-os/src/main/webapp/index.jsp b/ccsdk-app-os/src/main/webapp/index.jsp
new file mode 100644 (file)
index 0000000..e02bb6b
--- /dev/null
@@ -0,0 +1,5 @@
+<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+
+<%-- Redirected because we can't set the welcome page to a virtual URL. --%>
+<%-- Forward to the intended start page to reduce frustration for new users. --%> 
+<c:redirect url="/ecd"></c:redirect>
diff --git a/ccsdk-app-os/src/main/webapp/manifest.jsp b/ccsdk-app-os/src/main/webapp/manifest.jsp
new file mode 100644 (file)
index 0000000..417825f
--- /dev/null
@@ -0,0 +1,28 @@
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+    pageEncoding="UTF-8"%>
+<%
+       // Read contents of maven-generated manifest file.
+       final String path = "/META-INF/MANIFEST.MF";
+       java.io.InputStream input = getServletContext().getResourceAsStream(path);
+       java.io.InputStreamReader reader = new java.io.InputStreamReader(input, "UTF-8");
+       char [] buf = new char[1024];
+       int length = reader.read(buf, 0, buf.length);
+       final String manifest = new String(buf, 0, length);
+       reader.close();
+       input.close();
+%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Manifest</title>
+</head>
+<body>
+<h2>
+Contents of file <%= path %>:
+</h2>
+<pre>
+<%= manifest %>
+</pre>
+</body>
+</html>
index f6a95cf..d103674 100644 (file)
@@ -6,12 +6,12 @@
        <parent>
            <groupId>org.onap.ccsdk.dashboard</groupId>
            <artifactId>ccsdk-app-parent</artifactId>
-           <version>1.3.2-SNAPSHOT</version>
+           <version>1.4.0-SNAPSHOT</version>
        </parent>
 
        <groupId>org.onap.ccsdk.dashboard</groupId>
        <artifactId>ccsdk-app-overlay</artifactId>
-       <version>1.3.2-SNAPSHOT</version>
+       <version>1.4.0-SNAPSHOT</version>
        <packaging>war</packaging>
        <name>ONAP Operations Manager Dashboard overlay</name>
        <description>CCSDK Dashboard web resources</description>
                <skiptests>true</skiptests>
        </properties>
 
        <build>
                <plugins>
                        <!-- Silence Eclipse warnings by declaring Java 1.8 class output format -->
+                       <!-- 
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-compiler-plugin</artifactId>
@@ -34,6 +36,7 @@
                                        <target>1.8</target>
                                </configuration>
                        </plugin>
+                       -->
        </plugins>
        </build>
 
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-controllers.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-controllers.js
deleted file mode 100644 (file)
index c764165..0000000
+++ /dev/null
@@ -1,464 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-appDS2.controller('blueprintTableController', function($rootScope, $scope, $log, $modal, modalService, BlueprintService) {     
-       'use strict';
-
-       // Controls logging in this controller
-       var debug = false;
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       // models for controls on screen
-       $scope.ecdapp.tableData = [];
-       $scope.ecdapp.currentPageNum = 1;       
-       $scope.ecdapp.viewPerPage = 10;
-       // other
-       $scope.ecdapp.errMsg = null;
-       $scope.ecdapp.isDataLoading = true;
-       $scope.ecdapp.isRequestFailed = false;
-
-       /**
-        * Loads the table. Interprets the remote controller's response and copies 
-        * to scope variables. The response is either list to be assigned to 
-        * tableData, or an error to be shown.
-        */
-       $scope.ecdapp.loadTable = function() {
-               $scope.ecdapp.isDataLoading = true;
-               BlueprintService.getBlueprints($scope.ecdapp.currentPageNum, $scope.ecdapp.viewPerPage)
-                       .then(function(jsonObj) {
-                       if (jsonObj.error) {
-                               $log.error("blueprintController.loadTable failed: " + jsonObj.error);
-                               $scope.ecdapp.isRequestFailed = true;
-                               $scope.ecdapp.errMsg = jsonObj.error;
-                               $scope.ecdapp.tableData = [];
-                       } else {
-                               if (debug)
-                                       $log.debug("bluePrintController.loadTable succeeded, size " + jsonObj.data.length); 
-                               $scope.ecdapp.isRequestFailed = false;
-                               $scope.ecdapp.errMsg = null;
-                               $scope.ecdapp.totalPages = jsonObj.totalPages;
-                               $scope.ecdapp.tableData = jsonObj.items;
-                       }                       
-                       $scope.ecdapp.isDataLoading = false;
-               }, function(error) {
-                       $log.error("blueprintController.loadTable failed: " + error);
-                       $scope.ecdapp.isRequestFailed = true;
-                       $scope.ecdapp.errMsg = error;
-                       $scope.ecdapp.tableData = [];
-                       $scope.ecdapp.isDataLoading = false;
-               });
-       };
-       
-       /**
-        * Invoked at first page load AND when
-        * user clicks on the B2B pagination control. 
-        */
-       $scope.pageChangeHandler = function(page) {
-               // console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page);
-               $scope.ecdapp.currentPageNum = page;
-               $scope.ecdapp.loadTable();
-       }
-       
-       /**
-        * Shows a modal pop-up with blueprint content. 
-        * Passes data in via an object named "message". 
-        */
-       $scope.ecdapp.viewBlueprintModalPopup = function(blueprint) {
-               $scope.ecdapp.editBlueprint = null;
-               var modalInstance = $modal.open({
-                       templateUrl : 'blueprint_view_popup.html',
-                       controller : 'blueprintViewCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-medium',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               blueprint : blueprint
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function() {
-                       // No response.
-               });
-       };
-       
-       /**
-        * Shows a modal pop-up to upload a blueprint. 
-        * Passes data in via an object named "message". 
-        * On success, updates the table.
-        */
-       $scope.ecdapp.uploadBlueprintModalPopup = function() {
-               $scope.ecdapp.editBlueprint = null;
-               var modalInstance = $modal.open({
-                       templateUrl : 'blueprint_upload_popup.html',
-                       controller : 'blueprintUploadCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-small',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               blueprint : $scope.ecdapp.editBlueprint,
-                                               blueprintList : $scope.ecdapp.tableData
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       if (debug)
-                               $log.debug('uploadBlueprintModalPopup: response: ' + JSON.stringify(response));
-                       if (response == null) {
-                               // $log.debug('user closed dialog');
-                       }
-                       else {
-                               if (response.error != null) {
-                                       $log.error('uploadBlueprintModalPopup failed: ' + response.error);
-                                       alert('Failed to upload blueprint:\n' + response.error);
-                               }
-                               else {
-                                       // success, get the updated list.
-                                       $scope.ecdapp.loadTable();
-                               }
-                       }
-               });
-       };
-       
-    /**
-        * Shows a modal pop-up to create a deployment from a blueprint. 
-        * Passes data in via an object named "message". 
-        */
-       $scope.ecdapp.deployBlueprintModalPopup = function(blueprint) {
-               var modalInstance = $modal.open({
-                       templateUrl : 'blueprint_deploy_popup.html',
-                       controller : 'blueprintDeployCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-medium',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               blueprint : blueprint
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       if (debug)
-                               $log.debug('deployBlueprintModalPopup: response: ' + JSON.stringify(response));
-                       if (response == null) {
-                               if (debug)
-                                       $log.debug('user closed dialog');
-                       }
-                       else {
-                               if (response.error != null) {
-                                       $log.error('deployBlueprintModalPopup failed: ' + response.error);
-                                       alert('Failed to deploy blueprint:\n' + response.error);
-                                       // No need to update THIS table.
-                                       // Must switch to deployments page to see result?  Awkward.
-                               }
-                       }
-               });
-       };
-
-       /**
-        * Shows a modal pop-up to confirm deletion. 
-        * On successful completion, updates the table.
-        */
-       $scope.ecdapp.deleteBlueprintModalPopup = function(blueprint) {
-               modalService.popupConfirmWin("Confirm", "Delete blueprint with ID '"
-                               + blueprint.id + "'?", function() {
-                       BlueprintService.deleteBlueprint(blueprint.id).then(
-                                       function(response) {
-                                               if (debug)
-                                                       $log.debug('deleteBlueprintModalPopup: response: ' + JSON.stringify(response));
-                                               if (response && response.error) {
-                                                       // $log.error('deleteBlueprint failed: ' + response.error);
-                                                       alert('Failed to delete blueprint:\n' + response.error);
-                                               }
-                                               else {
-                                                       // No response body on success.
-                                                       $scope.ecdapp.loadTable();
-                                               }
-                                       },
-                                       function(error) {
-                                               $log.error('BlueprintService.deleteBlueprint failed: ' + error);
-                                               alert('Service failed to delete blueprint:\n' + error);
-                                       });
-               });
-       };
-
-       // Populate the table on load.  Note that the b2b selector code
-       // sets the page-number value, and the change event calls load table.
-       // Do not call this here to avoid double load: 
-       // $scope.ecdapp.loadTable();
-
-});
-
-/*************************************************************************/
-
-appDS2.controller('blueprintUploadCtrl', function(
-               $scope, $log, $modalInstance, message, BlueprintService) {
-
-       'use strict';
-       
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'Upload Blueprint';
-       $scope.ecdapp.uploadRequest = 
-               {
-                       blueprint_id : '',
-                       blueprint_filename : '',
-                       zip_url : ''
-               };
-
-       /**
-        * Validates content of user-editable fields.
-        * Uses the list in message.feedList 
-        * Returns null if all is well, 
-        * a descriptive error message otherwise.
-        */
-       $scope.ecdapp.validateRequest = function(uploadRequest) {
-               if (uploadRequest == null)
-                       return "No data found.\nPlease enter some values.";
-               if (uploadRequest.blueprint_id == null || uploadRequest.blueprint_id.trim() === '')
-                       return "ID is required.\nPlease enter a value.";
-               if (uploadRequest.blueprint_filename == null || uploadRequest.blueprint_filename.trim() === '')
-                       return "File name is required.\nPlease enter a value.";
-               if (uploadRequest.blueprint_filename.toLowerCase().substr(-4) !== 'yaml')
-                       return "File name must end with YAML.\nPlease use that suffix.";
-               if (uploadRequest.zip_url == null || uploadRequest.zip_url.trim() === '')
-                       return "Zip file URL is required.\nPlease enter a value.";
-               return null;
-       }
-       
-       $scope.ecdapp.uploadBlueprint = function(uploadRequest) {
-               var validateMsg = $scope.ecdapp.validateRequest(uploadRequest);
-               if (validateMsg != null) {
-                       alert('Invalid upload request:\n' + validateMsg);
-                       return;                 
-               }
-               BlueprintService.uploadBlueprint(uploadRequest)
-                       .then(function(response) {
-                               // $log.debug('blueprintPopupCtrl: response: ' + response);
-                               if (response.error)
-                                       alert('Failed to upload blueprint:\n' + response.error);
-                               else    
-                                       $modalInstance.close(response);
-                       },
-                       function (error) {
-                               $log.error('blueprintUploadCtrl: error while uploading: ' + error);
-                               alert('Server rejected upload request:\n' + error);
-                       }
-               );
-
-       };
-
-});
-
-/*************************************************************************/
-
-appDS2.controller('blueprintViewCtrl', function(
-               $scope, $log, message, BlueprintService) {
-
-       'use strict';
-       
-       var debug = false;
-       
-       if (debug)
-               $log.debug("blueprintViewCtrl.message: " + JSON.stringify(message));
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.blueprintId = message.blueprint.id;
-       
-       $scope.ecdapp.label = 'View Blueprint ' + message.blueprint.id;
-
-       // Fetch the blueprint
-       $scope.ecdapp.isDataLoading = true;
-       BlueprintService.viewBlueprint(message.blueprint.id).then(function(jsonObj) {
-               if (debug)
-                       $log.debug("blueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj));
-               if (jsonObj.error) {
-                       $scope.ecdapp.errMsg = 'Request Failed';
-               }
-               else {
-                       $scope.ecdapp.blueprint = jsonObj.content;
-               }
-               $scope.ecdapp.isDataLoading = false;
-       }, function(error) {
-               $scope.ecdapp.isDataLoading = false;
-               alert('Failed to get blueprint. Please retry.');
-               $log.error("blueprintViewCtrl failed: " + error);
-       });
-       
-});
-
-
-/*************************************************************************/
-
-appDS2.controller('blueprintDeployCtrl', function(
-               $scope, $log, $modalInstance, message, DeploymentService) {
-
-       'use strict';
-       
-       // Controls logging in this controller
-       var debug = false;
-       
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'Deploy Blueprint';
-
-       // Cache the input parameter names for validation
-       if (debug)
-               $log.debug('blueprintDeployCtrl: inputs: ' + JSON.stringify(message.blueprint.plan.inputs));
-       $scope.ecdapp.inputsDict = message.blueprint.plan.inputs;
-
-       // Copy the input parameter names and default values
-       let inputsAndDefaults = {};
-       for (var pkey in message.blueprint.plan.inputs) {
-               if (debug)
-                       $log.debug('blueprintDeployCtrl: checking key ' + pkey);
-               let dval = message.blueprint.plan.inputs[pkey].default;
-               if (! dval)
-                       dval = '';
-               inputsAndDefaults[pkey] = dval;
-       }
-       if (debug)
-               $log.debug('blueprintDeployCtrl: inputsAndDefaults: ' + JSON.stringify(inputsAndDefaults));
-       
-       // Create an object for edit
-       $scope.ecdapp.editRequest = {
-               deployment_id : '',
-               blueprint_id : message.blueprint.id,
-               fileModel : null,
-               parmFileDict : inputsAndDefaults
-       };
-
-       /**
-        * Handler for file-read event reads file, parses YAML, validates content.
-        */
-       var fileReader = new FileReader();
-       fileReader.onload = function(event) {
-               let yamlString = fileReader.result;
-               if (debug)
-                       $log.debug('fileReader.onload: read: ' + yamlString);
-               let ydict = {};
-               try {
-                       ydict = YAML.parse(yamlString);
-               }
-               catch (ex) {
-                       alert('Failed to parse file as YAML:\n' + ex);
-               }
-               // Process the file
-               for (var ykey in ydict) {
-                       let yval = ydict[ykey];
-                       if (debug)
-                               $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey);
-                       // Allow only expected keys with scalar values
-                       if (! (ykey in $scope.ecdapp.editRequest.parmFileDict))
-                               alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey);
-                       else if (typeof yval !== 'string' && typeof yval !== 'number')
-                               alert('Unexpected file content:\nNot a simple key-value pair:\n' + ykey);
-                       else
-                               $scope.ecdapp.editRequest.parmFileDict[ykey] = yval;
-               }
-               if (debug)
-                       $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict));
-
-               // Update table in all cases 
-               $scope.$apply();
-       }
-
-       // Handler for file-select event
-       $scope.handleFileSelect = function() {
-               if (debug)
-                       $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name);
-               fileReader.readAsText($scope.ecdapp.editRequest.fileModel);
-       };
-               
-       /**
-        * Validates content of user-editable fields.
-        * Returns null if all is well, 
-        * a descriptive error message otherwise.
-        */
-       $scope.ecdapp.validateRequest = function(editRequest) {
-               if (editRequest == null)
-                       return 'No data found.\nPlease enter some values.';
-               if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '')
-                       return 'Deployment ID is required.\nPlease enter a value.';
-               if (editRequest.blueprint_id == null || editRequest.blueprint_id.trim() == '')
-                       return 'Blueprint ID is required.\nPlease enter a value.';
-               // Check that every file parameter is defined by blueprint
-               for (var pkey in $scope.ecdapp.editRequest.parmFileDict) {
-                       // Defined in blueprint?
-                       if (! $scope.ecdapp.inputsDict[pkey]) 
-                               return 'Unexpected input parameter\n' + pkey;
-                       // Populated?
-                       let parmVal = $scope.ecdapp.editRequest.parmFileDict[pkey];
-                       if (parmVal == null || (typeof (parmVal) === 'string' && parmVal.trim().length == 0))
-                               return 'Missing value for parameter\n' + pkey;
-               }
-               // Check that a value is supplied for every expected input
-               for (var bkey in $scope.ecdapp.inputsDict) {
-                       if (! $scope.ecdapp.editRequest.parmFileDict[bkey]) 
-                               return 'Missing input parameter\n' + bkey;
-               }
-               return null;
-       }
-       
-       $scope.ecdapp.deployBlueprint = function(editRequest) {
-               if (debug)
-                       $log.debug('deployBlueprint: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest));
-               var validateMsg = $scope.ecdapp.validateRequest(editRequest);
-               if (validateMsg != null) {
-                       alert('Invalid Request:\n' + validateMsg);
-                       return;                 
-               }
-               // Create request with key:value parameters dictionary
-               let deployRequest =     {
-                       deployment_id : editRequest.deployment_id, 
-                       blueprint_id : editRequest.blueprint_id,
-                       parameters : {}
-               };
-               for (var pkey in $scope.ecdapp.editRequest.parmFileDict) 
-                       deployRequest.parameters[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey];
-               if (debug) 
-                       $log.debug('deployBlueprint: deployRequest is ' + JSON.stringify(deployRequest));
-               
-               DeploymentService.deployBlueprint(deployRequest)
-                       .then(function(response) {
-                               if (response.error)
-                                       alert('Failed to deploy blueprint:\n' + response.error);
-                               else    
-                                       $modalInstance.close(response);
-                       },
-                       function (error) {
-                               $log.error('blueprintDeployCtrl: error while deploying: ' + error);
-                               alert('Server rejected deployment request:\n' + error);
-                       }
-               );
-
-       };
-
-});
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-service.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint-service.js
deleted file mode 100644 (file)
index f058b09..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-appDS2.factory('BlueprintService', function ($http, $q, $log) {
-       return {
-               /**
-                * Gets one page of blue prints objects.
-                * @param {Number} pageNum - page number; e.g., 1 
-                * @param {Number} viewPerPage - number of items per page; e.g., 25
-                * @return {JSON} Response object from remote side
-                */
-               getBlueprints: function(pageNum,viewPerPage) {
-                       // cache control for IE
-                       let  cc = "&cc=" + new Date().getTime().toString();
-                       let url = 'blueprints?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc;
-                       return $http({
-                                       method: 'GET',
-                                       url: url,
-                                       cache: false,
-                                       responseType: 'json' 
-                       }).then(function(response) {
-                               if (response.data == null || typeof response.data != 'object') 
-                                       return $q.reject('BlueprintService.getBlueprints: response.data null or not object');
-                               else 
-                                       return response.data;
-                       }, 
-                       function(error) {
-                               $log.error('BlueprintService.getBlueprints failed: ' + JSON.stringify(error));
-                               return $q.reject(error.statusText);
-                       });
-               },
-               
-               /**
-                * Gets blueprint content.
-                * @return {JSON} Response object from remote side
-                */
-               viewBlueprint: function(id) {
-                       // cache control for IE
-                       let url = 'viewblueprints/' + id;
-                       return $http({
-                                       method: 'GET',
-                                       url: url,
-                                       cache: false,
-                                       responseType: 'json' 
-                       }).then(function(response) {
-                               if (response.data == null || typeof response.data != 'object') 
-                                       return $q.reject('BlueprintService.viewBlueprint: response.data null or not object');
-                               else 
-                                       return response.data;
-                       }, 
-                       function(error) {
-                               $log.error('BlueprintService.viewBlueprint failed: ' + JSON.stringify(error));
-                               return $q.reject(error.statusText);
-                       });
-               },
-
-               uploadBlueprint: function(uploadRequest) {
-                       let url = 'blueprints';
-                       return $http({
-                                       method: 'POST',
-                                       url: url,
-                                       data: uploadRequest,
-                                       responseType: 'json' 
-                       }).then(function(response) {
-                               if (response.data == null || typeof response.data != 'object') 
-                                       return $q.reject('BlueprintService.uploadBlueprint: response.data null or not object');
-                               else 
-                                       return response.data;
-                       }, 
-                       function(error) {
-                               $log.error('BlueprintService.uploadBlueprint failed: ' + JSON.stringify(error));
-                               return $q.reject(error.statusText);
-                       });
-               },              
-
-               deleteBlueprint: function(id) {
-                       let url = 'blueprints/' + id;
-                       return $http({
-                                       method: 'DELETE',
-                                       url: url,
-                                       cache: false,
-                                       responseType: 'json' 
-                       }).then(function(response) {
-                               // This is called on response code 200..299.
-                               // On success, response.data is null.
-                               // On failure, response.data has an error message.
-                               return response.data;
-                       }, 
-                       function(error) {
-                               $log.error('BlueprintService.deleteBlueprint failed: ' + JSON.stringify(error));
-                               return $q.reject(error.statusText);
-                       });
-               }
-               
-       };
-});
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_popups.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_popups.html
deleted file mode 100644 (file)
index ee92d84..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-<script type="text/ng-template" id="blueprint_upload_popup.html">
-
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content">
-
-               <div class="row-nowrap">
-                       <div class="span12">
-                               <div class="form-row">
-                                       <label for="blueprintId">*Blueprint ID</label>
-                                       <div class="field-group">
-                                               <!--autofocus is HTML5 attribute; doesn't work in Firefox-->
-                                               <input id="blueprintId" class="span12" type="text" data-ng-model="ecdapp.editBlueprint.blueprint_id" autofocus>
-                                       </div>
-                               </div>
-                       </div> 
-               </div>                  
-                       
-               <div class="row-nowrap">
-                       <div class="span12">
-                               <div class="form-row">
-                                       <label for="blueprintFileName">*File Name</label>
-                                       <div class="field-group">
-                                               <input id="blueprintFileName" class="span12" type="text" data-ng-model="ecdapp.editBlueprint.blueprint_filename">
-                                       </div>
-                               </div>                  
-                       </div>
-               </div>
-
-               <div class="row-nowrap">
-                       <div class="span12">
-                               <div class="form-row">
-                                       <label for="zipFileUrl">*Zip File URL</label>
-                                       <div class="field-group">
-                                               <input id="zipFileUrl" class="span12" type="text" data-ng-model="ecdapp.editBlueprint.zip_url">
-                                       </div>
-                               </div>                  
-                       </div>
-               </div>
-
-       </div>
-
-       <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-               <div class="cta-button-group in">
-                       <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="ecdapp.uploadBlueprint(ecdapp.editBlueprint);">
-                               Save
-                       </button>
-                       <button class="btn btn-small" type="button"
-                               ng-click="$dismiss('cancel')">
-                               Cancel
-                       </button>
-               </div>
-       </div>
-
-</script>
-
-<script type="text/ng-template" id="blueprint_view_popup.html">
-
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content">
-
-               <!-- show progress indicator -->
-               <div ng-show="ecdapp.isDataLoading">
-                       <div class="span" style="margin-bottom:20px;">
-                       <i class="icon-primary-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                       Please wait while the content loads.
-               </div>
-               </div>
-
-               <div ng-show="ecdapp.errMsg">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-       
-               <div ng-hide="ecdapp.errMsg">
-                       <pre>{{ecdapp.blueprint}}</pre>
-               </div>
-
-       </div>
-
-       <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-               <div class="cta-button-group in">
-                       <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="$dismiss('cancel');">
-                               Close
-                       </button>
-               </div>
-       </div>
-
-</script>
-
-<script type="text/ng-template" id="blueprint_deploy_popup.html">
-
-       <style>
-       .ecd-parameter-table
-       {
-           border:   1px;
-       overflow: auto;
-       }
-       .ecd-parameter-table th 
-       {
-               font-size: 1.4rem;
-       }
-       </style>
-
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content">
-               <div class="row-nowrap">
-                       <div class="span12">
-                               <label for="blueprintFileName">*Deployment ID</label>
-                               <!--autofocus is HTML5 attribute; doesn't work in Firefox-->
-                               <input id="blueprintFileName" class="span12" type="text" data-ng-model="ecdapp.editRequest.deployment_id" autofocus/>
-                       </div>
-                       <div class="span12">
-                               <label for="blueprintId">Blueprint ID</label>
-                               <!--not editable-->
-                               <input id="blueprintId" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.editRequest.blueprint_id"/>
-                       </div> 
-               </div>                  
-                       
-               <div class="row-nowrap">
-                       <div class="span12">
-                               <div class="form-row">
-                                       <label for="parameters">*Parameters</label>
-                                       <div b2b-file-drop file-model="ecdapp.editRequest.fileModel" on-drop="handleFileSelect()" align="center">
-                                               <span b2b-file-link file-model="ecdapp.editRequest.fileModel" on-file-select="handleFileSelect()" >
-                                               Drag &amp; drop a parameters YAML file here, or click to browse.
-                                                       </span>
-                               </div>
-                       </div>
-                               <div class="ecd-parameter-table">
-                                       <table id="parameters">
-                                               <tr id="ecd-table-header">
-                                                       <th width="40%">Name</th>
-                                                       <th width="60%">Value</th>
-                                               </tr>
-                               <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict">
-                                                       <tr id="tr-rowData">
-                                                               <td ng-bind="pkey"/>
-                                                               <td ng-bind="pval"/>
-                                                       </tr>
-                                               </tbody>
-                                       </table>
-                               </div>
-                       </div>
-               </div>
-
-       </div>
-
-       <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-               <div class="cta-button-group in">
-                       <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="ecdapp.deployBlueprint(ecdapp.editRequest);">
-                               Save
-                       </button>
-                       <button class="btn btn-small" type="button"
-                               ng-click="$dismiss('cancel')">
-                               Cancel
-                       </button>
-               </div>
-       </div>
-
-</script>
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_table.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/blueprint_table.html
deleted file mode 100644 (file)
index 3ce60b9..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-<div id="page-content">
-
-       <h1 class="heading-page" id="blueprints-page">Blueprints</h1>
-       
-       <!-- show progress indicator -->
-       <div ng-show="ecdapp.isDataLoading">
-               <div class="span" style="margin-bottom:20px;">
-               <i class="icon-primary-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-               Please wait while the content loads.
-           </div>
-       </div>
-
-       <div ng-hide="ecdapp.isDataLoading">
-               
-               <div id="button-search-row">
-                       <button class="btn btn-alt btn-small" 
-                               type="submit"
-                               ng-click="ecdapp.uploadBlueprintModalPopup();"> 
-                               Upload Blueprint...
-                       </button>
-                       <div style="float:right;">
-                          <div class="form-field form-field__small"> 
-                                       <input 
-                                               type="text"
-                                               placeholder="Search Blueprints"
-                                               ng-model="ecdapp.searchString"/>
-                               </div>
-                       </div>
-               </div>
-
-               <div ng-show="ecdapp.isRequestFailed">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-       
-               <div ng-hide="ecdapp.isRequestFailed">
-       
-               <div 
-                       b2b-table 
-                       id="blueprints-table"
-                       class="b2b-table-div" 
-                       table-data="ecdapp.tableData" 
-                       search-string="ecdapp.searchString" 
-                       current-page="ecdapp.currentPageIgnored"
-                       next-sort="ecdapp.nextSortIgnored">
-       
-                       <table>
-                       
-                           <thead b2b-table-row type="header"> 
-                                               <tr id="th-header-row">
-                                                       <th b2b-table-header key="id">ID</th>
-                                                       <th b2b-table-header key="main_file_name">File Name</th>
-                                                       <th b2b-table-header key="description">Description</th>
-                                                       <th b2b-table-header key="created_at">Created Date</th>
-                                                       <th b2b-table-header key="updated_at">Updated Date</th>
-                                                       <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th>
-                                               </tr>
-                                       </thead>
-                                       
-                           <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData">
-                                               <tr id="tr-rowData">
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.id"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.main_file_name"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.description"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.created_at"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.updated_at"/>                                          
-                                                       <td b2b-table-body> 
-                                                       <div ng-click="ecdapp.viewBlueprintModalPopup(rowData);">
-                                                               <a href="" title="View blueprint" class="icon-people-preview ecd-icon-action"></a>
-                                                       </div>
-                                                       <div ng-click="ecdapp.deployBlueprintModalPopup(rowData);">
-                                                               <a href="" title="Deploy blueprint" class="icon-datanetwork-cloudupload ecd-icon-action"></a>
-                                                       </div>
-                                                       <div ng-click="ecdapp.deleteBlueprintModalPopup(rowData);">
-                                                               <a href="" title="Delete blueprint" class="icon-misc-trash ecd-icon-action"></a>
-                                                       </div>
-                                               </td>
-                                               </tr>
-                                       </tbody>
-                               </table>
-                       </div> 
-               
-               <div b2b-pagination="" total-pages="ecdapp.totalPages" 
-                                               current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler"
-                                               role="navigation">
-               </div>
-                                                       
-               <div style="height: 10px;">
-                       <!-- space between page number and black footer -->
-               </div>
-               
-       </div><!-- loading -->
-       
-</div><!-- page content -->
index 1e80082..f89ce76 100644 (file)
@@ -1,26 +1,6 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
 appDS2.controller('deploymentTableController', function(
-               $rootScope, $scope, $log, $modal, DeploymentService) {
+               $rootScope, $scope, $log, $modal, $routeParams, DeploymentService, ControllerService,
+               InventoryDeploymentService, localStorageService, $interval) {
 
        'use strict';
 
@@ -36,17 +16,469 @@ appDS2.controller('deploymentTableController', function(
        // other
        $scope.ecdapp.errMsg = null;
        $scope.ecdapp.isDataLoading = true;
-       $scope.ecdapp.isRequestFailed = false;
+       $scope.ecdapp.isRequestFailed = false;  
+       $scope.ecdapp.useCache = true;
+       $scope.ecdapp.groupByTenant = false;
+       $scope.ecdapp.filterByUser = true;
+  $scope.ecdapp.cache_switch = {
+      value: true
+  };
+  $scope.ecdapp.getTenants = function() {  
+    ControllerService.getTenants()
+    .then(function(jsonObj) {
+      if (jsonObj.error) {
+        $log.error("blueprintController.getTenants failed: " + jsonObj.error);
+        $scope.ecdapp.isRequestFailed = true;
+        $scope.ecdapp.errMsg = jsonObj.error;
+        $scope.ecdapp.tableData = [];
+      } else {
+        var tenants = [];
+        for (var tenIndx = 0; tenIndx < jsonObj.items.length; tenIndx++) {
+          tenants.push(jsonObj.items[tenIndx].name);
+        }
+        $scope.ecdapp.availableTenants = tenants;
+        if ($scope.ecdapp.availableTenants != undefined) {
+          $scope.ecdapp.selectedTenant = $scope.ecdapp.availableTenants[0];
+        }
+        localStorageService.set('tenants', JSON.stringify(tenants));
+      }     
+    }, function(error) {
+      $log.error("blueprintController.getTenants failed: " + error);
+      $scope.ecdapp.isRequestFailed = true;
+      $scope.ecdapp.errMsg = error;
+    });
+  };
+  
+  $scope.ecdapp.availableTenants = JSON.parse(localStorageService.get('tenants'));
+  if ($scope.ecdapp.availableTenants == undefined) {
+    $scope.ecdapp.getTenants();
+  } else {
+    //$scope.ecdapp.selectedTenant = $scope.ecdapp.availableTenants[0];
+    $scope.ecdapp.selectedTenant = '';
+  }
+  // searching
+  $scope.ecdapp.searchBy = $routeParams.depId;
+  if ($scope.ecdapp.searchBy == undefined) {
+    $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" + 
+    "cache:" + $scope.ecdapp.useCache + ";" +"owner:" + $scope.userId + ";";
+    //+ "user:" + $scope.ecdapp.filterByUser + ";";
+  } else {
+    if ($scope.ecdapp.searchBy.includes("owner")) {
+      if ($scope.ecdapp.searchBy.split(":")[1] === "group") {
+        $scope.ecdapp.filterByUser = false;
+        $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" + 
+        "cache:" + $scope.ecdapp.useCache + ";";
+      }
+    } else {   
+      $scope.ecdapp.selectedTenant = $scope.ecdapp.searchBy.split(";")[0].split(":")[1]
+    }
+  }
 
+  //$scope.ecdapp.selectedTenant = "default_tenant";
+  //if ($scope.ecdapp.availableTenants != undefined) {
+   // $scope.ecdapp.selectedTenant = $scope.ecdapp.availableTenants[0];
+  //}
+  
+  // sorting
+  $scope.ecdapp.sortBy = null;
+
+  $scope.ecdapp.isDisabled = false;
+  $scope.ecdapp.isDetailView = false;
+  $scope.ecdapp.isHelmType = false;
+  $scope.ecdapp.aafUsernameString;
+  $scope.ecdapp.dcaeTargetTypeString;
+  $scope.ecdapp.selectedSrvc;
+  $scope.ecdapp.usingAafFilter = false;
+  $scope.ecdapp.usingDcaeTargetTypeFilter = false;
+  $scope.ecdapp.selectedOwner;
+  $scope.ecdapp.availableServices; // = JSON.parse(localStorageService.get('deplNames'));
+  $scope.ecdapp.selectedServices;
+  $scope.ecdapp.bpOwners = JSON.parse(localStorageService.get('bpOwners'));
+
+  $scope.ecdapp.availableStatus = 
+    ['pending','started','cancelling','force_cancelling','cancelled','terminated','failed'];
+  $scope.ecdapp.selectedStatus;
+
+  $scope.ecdapp.showingMoreFilters = false;
+
+  $scope.ecdapp.toggleMoreFilters = function() {      
+    $scope.ecdapp.showingMoreFilters = !$scope.ecdapp.showingMoreFilters;
+  };
+
+  
+    // Handler for disabling non aaf/dcae target type search fields
+    $scope.ecdapp.handleDisableOtherFields = function() {
+      //If using aaf filter, disable others
+      //and clear the dcae target type field
+      if ($scope.ecdapp.aafUsernameString == '' || typeof $scope.ecdapp.aafUsernameString == "undefined")
+        $scope.ecdapp.usingAafFilter = false;
+      else {
+        $scope.ecdapp.usingAafFilter = true;
+        $scope.ecdapp.dcaeTargetTypeString = '';
+      }
+        
+      //If using dcae target type filter, disable others
+      //and clear the aaf filter field
+      if ($scope.ecdapp.dcaeTargetTypeString == '' || typeof $scope.ecdapp.dcaeTargetTypeString == "undefined")
+          $scope.ecdapp.usingDcaeTargetTypeFilter = false;
+      else {
+        $scope.ecdapp.usingDcaeTargetTypeFilter = true;
+        $scope.ecdapp.aafUsernameString = '';
+      }
+    };
+
+    // get the blueprints summary list
+    $scope.ecdapp.bp = [];
+    $scope.ecdapp.getAllAuthBpList = function() {
+      InventoryBlueprintService.getBlueprintsSummary()
+      .then(function(jsonObj) {
+        if (jsonObj.error) {
+          $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + jsonObj.error);
+          $scope.ecdapp.errMsg = jsonObj.error;
+          $scope.ecdapp.bp = [];
+        } else {
+          $scope.ecdapp.errMsg = null;
+          $scope.ecdapp.bp = jsonObj;
+        }     
+        $scope.ecdapp.isDataLoading = false;
+      }, function(error) {
+        $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + error);
+        $scope.ecdapp.errMsg = error;
+        $scope.ecdapp.bp = [];
+        $scope.ecdapp.isDataLoading = false;
+      });
+    };
+    
+  $scope.ecdapp.getDeploymentsList = function() {
+    InventoryDeploymentService.getDeploymentList($scope.ecdapp.searchBy).then(
+        function(jsonObj) {
+          if (jsonObj.error) {
+            $log.error("inventoryDeploymentController.getDeploymentList failed: "
+                + jsonObj.error);
+            $scope.ecdapp.availableServices = [];
+          } else {
+            //localStorageService.set('deplNames', JSON.stringify(jsonObj));
+            $scope.ecdapp.availableServices = jsonObj;
+              //JSON.parse(localStorageService.get('deplNames'));
+          }
+        },
+        function(error) {
+          $log.error("inventoryDeploymentController.getDeploymentList failed: "
+              + error);
+          $scope.ecdapp.availableServices = [];
+        });
+  };
+  
+  $scope.ecdapp.reloadTable = function() {
+    $scope.ecdapp.currentPageNum = 1;
+    $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";" 
+    +"cache:" + $scope.ecdapp.useCache + ";";
+    //+ "user:" + $scope.ecdapp.filterByUser + ";"; 
+    if ($scope.ecdapp.filterByUser) {
+      $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";";
+    }
+    $scope.ecdapp.searchString = '';
+    $scope.ecdapp.resetFilters();
+    $scope.ecdapp.loadTable();
+  };
+  
+  $scope.ecdapp.resetFilters = function() {
+    $scope.ecdapp.selectedServices = '';
+    $scope.ecdapp.selectedTenants = '';
+    $scope.ecdapp.selectedStatus = '';
+    $scope.ecdapp.selectedOwner = '';
+    $scope.ecdapp.isHelmType = false;
+    $scope.ecdapp.searchString = '';
+    $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";"
+    +"cache:" + $scope.ecdapp.useCache + ";";
+    if ($scope.ecdapp.filterByUser) {
+      $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";";
+    }
+    /*
+    $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";"
+    +"cache:" + $scope.ecdapp.useCache + ";"+ "user:" + $scope.ecdapp.filterByUser + ";";
+    */
+  };
+  $scope.ecdapp.filterBySvc = function() {
+    if ( typeof $scope.ecdapp.searchString != "undefined" && 
+        $scope.ecdapp.searchString != '') {     
+      if ($scope.ecdapp.searchString.includes("serviceRef:") ||
+          $scope.ecdapp.searchString.includes("tenant:") ||
+          $scope.ecdapp.searchString.includes("status:") ||
+          $scope.ecdapp.searchString.includes("helm:")) {
+        $scope.ecdapp.searchBy = $scope.ecdapp.searchString +";cache:" + $scope.ecdapp.useCache + ";";
+         // + "user:" + $scope.ecdapp.filterByUser + ";";
+      } else {
+        $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";"
+        $scope.ecdapp.searchBy += 'serviceRef:' + $scope.ecdapp.searchString +";cache:" + $scope.ecdapp.useCache + ";";
+          //+ "user:" + $scope.ecdapp.filterByUser + ";";
+      }
+      if ($scope.ecdapp.filterByUser) {
+        $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";";
+      }
+      $scope.ecdapp.searchTable();
+    }
+  };
+
+  $scope.ecdapp.extendedfilterSrch = function() {
+    /*
+    $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant +  ";" +
+    "cache:" + $scope.ecdapp.useCache + ";" + "user:" + $scope.ecdapp.filterByUser + ";";
+     * 
+     */
+    $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant +  ";" +
+    "cache:" + $scope.ecdapp.useCache + ";";
+    
+    if ( typeof $scope.ecdapp.selectedServices != "undefined" && 
+      $scope.ecdapp.selectedServices != '') {
+      var svcFilterStr = 'serviceRef:' + $scope.ecdapp.selectedServices.toString();
+      $scope.ecdapp.searchBy += svcFilterStr + ";"
+    }  
+    if ( typeof $scope.ecdapp.selectedOwner != "undefined" &&
+        $scope.ecdapp.selectedOwner != '') {
+      var ownerFilterStr = 'owner:' + $scope.ecdapp.selectedOwner.toString();
+      $scope.ecdapp.searchBy +=  ownerFilterStr + ';'
+    }
+    if ( typeof $scope.ecdapp.selectedStatus != "undefined" &&
+        $scope.ecdapp.selectedStatus != '') {
+      var statusFilterStr = 'status:' + $scope.ecdapp.selectedStatus.toString();
+      $scope.ecdapp.searchBy +=  statusFilterStr + ';'
+    }
+    if ( typeof $scope.ecdapp.isHelmType != "undefined" &&
+        $scope.ecdapp.isHelmType == true) {
+      var helmFilterStr = 'helm:' + $scope.ecdapp.isHelmType;
+      $scope.ecdapp.searchBy +=  helmFilterStr + ';'
+    }     
+  
+    if ($scope.ecdapp.filterByUser) {
+      $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";";
+    }
+    //If using AAF username filter, ignore other fields and do filtered search.
+    if ($scope.ecdapp.usingAafFilter) {
+          var aafFilterStr = 'aafUsername:' + $scope.ecdapp.aafUsernameString.toString();
+          $scope.ecdapp.searchBy = $scope.ecdapp.aafUsernameString.toString();
+          $scope.ecdapp.searchString = aafFilterStr + ';';
+          $scope.ecdapp.searchTableAafFilter();
+        }
+    else if ($scope.ecdapp.usingDcaeTargetTypeFilter) {
+        var dcaeTargetTypeFilterStr = 'dcaeTargetType:' + $scope.ecdapp.dcaeTargetTypeString.toString();
+        $scope.ecdapp.searchBy = $scope.ecdapp.dcaeTargetTypeString.toString();
+        $scope.ecdapp.searchString = dcaeTargetTypeFilterStr + ';';
+        $scope.ecdapp.searchTableDcaeTargetTypeFilter();
+      }
+    else {
+      $scope.ecdapp.searchString = $scope.ecdapp.searchBy;
+      $scope.ecdapp.searchTable();
+    }  
+  };
+
+  $scope.ecdapp.sortTable = function(sortBy) {
+    $scope.ecdapp.isDataLoading = true;
+    $scope.ecdapp.sortBy = sortBy;
+    DeploymentService.getDeployments($scope.ecdapp.currentPageNum,
+        $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, $scope.ecdapp.searchBy).then(
+            function(jsonObj) {
+              if (jsonObj.error) {
+                $log.error("DeploymentController.sortTable failed: "
+                    + jsonObj.error);
+                $scope.ecdapp.isRequestFailed = true;
+                $scope.ecdapp.errMsg = jsonObj.error;
+                $scope.ecdapp.tableData = [];
+              } else {
+                $scope.ecdapp.isRequestFailed = false;
+                $scope.ecdapp.errMsg = null;
+                $scope.ecdapp.totalPages = jsonObj.totalPages;
+                $scope.ecdapp.tableData = jsonObj.items;
+              }
+              $scope.ecdapp.isDataLoading = false;
+            },
+            function(error) {
+              $log.error("DeploymentController.sortTable failed: "
+                  + error);
+              $scope.ecdapp.isRequestFailed = true;
+              $scope.ecdapp.errMsg = error;
+              $scope.ecdapp.tableData = [];
+              $scope.ecdapp.isDataLoading = false;
+            });
+  };
+  /**
+   * Loads the table. Interprets the remote controller's response and copies
+   * to scope variables. The response is either a list to be assigned to
+   * tableData, or an error to be shown.
+   */
+  $scope.ecdapp.searchTable = function() {
+    $scope.ecdapp.isDataLoading = true;
+    $scope.ecdapp.showingMoreFilters = false;
+    if ($scope.ecdapp.currentPageNum != 1) {
+      $scope.ecdapp.currentPageNum = 1;
+    } else {
+      $scope.ecdapp.stopLoading();
+      DeploymentService.getDeployments($scope.ecdapp.currentPageNum,
+        $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, $scope.ecdapp.searchBy).then(
+            function(jsonObj) {
+              stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 180000, 100, false);
+              $scope.ecdapp.searchString = $scope.ecdapp.searchBy;
+              if (jsonObj.error) {
+                $log.error("DeploymentController.loadTable failed: "
+                    + jsonObj.error);
+                $scope.ecdapp.isRequestFailed = true;
+                $scope.ecdapp.errMsg = jsonObj.error;
+                $scope.ecdapp.tableData = [];
+              } else {
+                $scope.ecdapp.isRequestFailed = false;
+                $scope.ecdapp.errMsg = null;
+                $scope.ecdapp.totalPages = jsonObj.totalPages;
+                $scope.ecdapp.tableData = jsonObj.items;
+              }
+              $scope.ecdapp.isDataLoading = false;
+            },
+            function(error) {
+              $scope.ecdapp.searchString = $scope.ecdapp.searchBy;
+              $scope.ecdapp.searchBy = '';
+              $log.error("DeploymentController.loadTable failed: "
+                  + error);
+              $scope.ecdapp.isRequestFailed = true;
+              $scope.ecdapp.errMsg = error;
+              $scope.ecdapp.tableData = [];
+              $scope.ecdapp.isDataLoading = false;
+            });
+    }
+  };
+
+  /**
+   * Loads the table with AAF Filter. Interprets the remote controller's response and copies
+   * to scope variables. The response is either a list to be assigned to
+   * tableData, or an error to be shown.
+   */
+  $scope.ecdapp.searchTableAafFilter = function() {
+    $scope.ecdapp.isDataLoading = true;
+    $scope.ecdapp.showingMoreFilters = false;
+    if ($scope.ecdapp.currentPageNum != 1) {
+      $scope.ecdapp.currentPageNum = 1;
+    } else {
+      $scope.ecdapp.stopLoading();
+    InventoryDeploymentService.getDeploymentsAafFilter($scope.ecdapp.currentPageNum,
+        $scope.ecdapp.viewPerPage, $scope.ecdapp.searchBy).then(
+            function(jsonObj) {
+              stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 180000, 100, false);
+              $scope.ecdapp.searchString = $scope.ecdapp.searchBy;
+              if (jsonObj.error) {
+                $log.error("inventoryDeploymentController.loadTable failed: "
+                    + jsonObj.error);
+                $scope.ecdapp.isRequestFailed = true;
+                $scope.ecdapp.errMsg = jsonObj.error;
+                $scope.ecdapp.tableData = [];
+              } else {
+                $scope.ecdapp.isRequestFailed = false;
+                $scope.ecdapp.errMsg = null;
+                $scope.ecdapp.totalPages = jsonObj.totalPages;
+                $scope.ecdapp.tableData = jsonObj.items;
+                //$scope.ecdapp.updateTable();
+              }
+              $scope.ecdapp.isDataLoading = false;
+            },
+            function(error) {
+              $scope.ecdapp.searchString = $scope.ecdapp.searchBy;
+              $scope.ecdapp.searchBy = '';
+              $log.error("inventoryDeploymentController.loadTable failed: "
+                  + error);
+              $scope.ecdapp.isRequestFailed = true;
+              $scope.ecdapp.errMsg = error;
+              $scope.ecdapp.tableData = [];
+              $scope.ecdapp.isDataLoading = false;
+            });
+    }
+  };
+  
+  /**
+   * Loads the table with Dcae target type Filter. Interprets the remote controller's response and copies
+   * to scope variables. The response is either a list to be assigned to
+   * tableData, or an error to be shown.
+   */
+  $scope.ecdapp.searchTableDcaeTargetTypeFilter = function() {
+    $scope.ecdapp.isDataLoading = true;
+    $scope.ecdapp.showingMoreFilters = false;
+    if ($scope.ecdapp.currentPageNum != 1) {
+      $scope.ecdapp.currentPageNum = 1;
+    } else {
+      $scope.ecdapp.stopLoading();
+    InventoryDeploymentService.getDeploymentsDcaeTargetTypeFilter($scope.ecdapp.currentPageNum,
+        $scope.ecdapp.viewPerPage, $scope.ecdapp.searchBy).then(
+            function(jsonObj) {
+              stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 180000, 100, false);
+              $scope.ecdapp.searchString = $scope.ecdapp.searchBy;
+              if (jsonObj.error) {
+                $log.error("inventoryDeploymentController.loadTable failed: "
+                    + jsonObj.error);
+                $scope.ecdapp.isRequestFailed = true;
+                $scope.ecdapp.errMsg = jsonObj.error;
+                $scope.ecdapp.tableData = [];
+              } else {
+                $scope.ecdapp.isRequestFailed = false;
+                $scope.ecdapp.errMsg = null;
+                $scope.ecdapp.totalPages = jsonObj.totalPages;
+                $scope.ecdapp.tableData = jsonObj.items;
+                //$scope.ecdapp.updateTable();
+              }
+              $scope.ecdapp.isDataLoading = false;
+            },
+            function(error) {
+              $scope.ecdapp.searchString = $scope.ecdapp.searchBy;
+              $scope.ecdapp.searchBy = '';
+              $log.error("inventoryDeploymentController.loadTable failed: "
+                  + error);
+              $scope.ecdapp.isRequestFailed = true;
+              $scope.ecdapp.errMsg = error;
+              $scope.ecdapp.tableData = [];
+              $scope.ecdapp.isDataLoading = false;
+            });
+    }
+  }; 
+  $scope.ecdapp.stopLoading = function() {
+    if (angular.isDefined(stop)) {
+      $interval.cancel(stop);
+      stop = undefined;
+    }
+  };
+  
+  $scope.ecdapp.toggleRefresh = function() {
+    if ($scope.ecdapp.useCache === true) {
+        stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 180000, 100, false);
+      } else {
+        $scope.ecdapp.stopLoading();
+      }
+  };
+
+  if ($scope.ecdapp.useCache === true) {
+    stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 180000, 100, false);
+  }
+  
+  $scope.ecdapp.toggleUserFilt = function() {
+    if ($scope.ecdapp.filterByUser === true) {
+      $scope.ecdapp.groupByTenant = false;
+      $scope.ecdapp.selectedTenant = '';
+    } else {
+      $scope.ecdapp.searchString = '';
+    }
+    $scope.ecdapp.reloadTable();
+  }
+  
+  $scope.ecdapp.toggleTenantFilt = function() {
+    if ($scope.ecdapp.groupByTenant  === false) {
+      $scope.ecdapp.selectedTenant = '';
+    }
+  }
        /**
         * Loads the table. Interprets the remote controller's response and copies
         * to scope variables. The response is either a list to be assigned to
         * tableData, or an error to be shown.
         */
-       $scope.ecdapp.loadTable = function() {
+       $scope.ecdapp.loadTable = function(sortBy, searchBy) {
                $scope.ecdapp.isDataLoading = true;
+    //$scope.ecdapp.searchString = '';
+    $scope.ecdapp.sortBy = sortBy;
                DeploymentService.getDeployments($scope.ecdapp.currentPageNum,
-                               $scope.ecdapp.viewPerPage).then(
+                               $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, $scope.ecdapp.searchBy).then(
                                function(jsonObj) {
                                        if (jsonObj.error) {
                                                $log.error("deploymentController.loadTable failed: "
@@ -69,7 +501,13 @@ appDS2.controller('deploymentTableController', function(
                                        $scope.ecdapp.errMsg = error;
                                        $scope.ecdapp.tableData = [];
                                        $scope.ecdapp.isDataLoading = false;
+          var loc = location.pathname;
+          var loc1 = loc.replace("/", "");
+          var loc2 = loc1.replace("/ecd", "/login.htm");
+          alert("Session expired - Sign in again");
+          location.replace("/"+loc2);
                                });
+      $scope.ecdapp.getDeploymentsList();
        };
 
        /**
@@ -79,9 +517,186 @@ appDS2.controller('deploymentTableController', function(
        $scope.pageChangeHandler = function(page) {
                // console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page);
                $scope.ecdapp.currentPageNum = page;
-               $scope.ecdapp.loadTable();
+               //$scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";"; 
+    $scope.ecdapp.loadTable($scope.ecdapp.sortBy, $scope.ecdapp.searchBy);
        }
        
+       $scope.ecdapp.tenantChangeHandler = function() {
+         $scope.ecdapp.currentPageNum = 1;
+    $scope.ecdapp.searchBy = "tenant:" + $scope.ecdapp.selectedTenant + ";"
+    +"cache:" + $scope.ecdapp.useCache + ";";
+    //+ "user:" + $scope.ecdapp.filterByUser + ";"; 
+    if ($scope.ecdapp.filterByUser) {
+      $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";";
+    }
+    $scope.ecdapp.searchString = $scope.ecdapp.searchBy;
+    $scope.ecdapp.loadTable($scope.ecdapp.sortBy, $scope.ecdapp.searchBy);       
+       }
+       
+  //$scope.ecdapp.getTenants();
+  
+  /**
+   * modal pop-up for app reconfig operation
+   * 
+   */
+  $scope.ecdapp.reconfigDeploymentModalPopup = function(deployment) {
+    var modalInstance = $modal.open({
+      templateUrl : 'app_reconfig_view_popup.html',
+      controller : 'appReconfigCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve : {
+        message : function() {
+          var dataForPopup = {
+              deployment : deployment
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+      // No response.
+    });
+  };
+
+  /**
+   * Shows a modal pop-up to confirm deletion. 
+   * On successful completion, updates the table.
+   */
+  $scope.ecdapp.deleteDeploymentModalPopup = function(deployment) { 
+    deployment.onlyLatest = true;
+    var modalInstance = $modal.open({
+      templateUrl : 'inventory_deployment_delete_popup.html',
+      controller : 'deploymentDeleteCtrl',
+      sizeClass: 'modal-small',
+      resolve : {
+        message : function() {
+          var dataForPopup = {
+              deployment : deployment,
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+      if (debug)
+        $log.debug('deleteDeploymentPopup: response: ' + JSON.stringify(response));
+      if (response == null) {
+        // $log.debug('user closed dialog');
+      }
+      else {
+        if (response.error != null) {
+          $log.error('deleteDeploymentModalPopup failed: ' + response.error);
+          alert('Failed to delete deployment:\n' + response.error);
+        }
+        else {
+          $scope.ecdapp.viewDeploymentExecutionsModalPopup(deployment);
+        }
+      }
+    });
+  };
+
+  /**
+   * Shows a modal pop-up with executions for a deployment.
+   * Passes data in via an object named "deployment".
+   */
+  $scope.ecdapp.viewDeploymentExecutionsModalPopup = function(deployment) {
+    var modalInstance = $modal.open({
+      templateUrl : 'inventory_execution_view_popup.html',
+      controller : 'deploymentExecutionsViewCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve : {
+        message : function() {
+          var dataForPopup = {
+              deployment : deployment
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+      // No response.
+    });
+  };
+
+       
+  $scope.ecdapp.viewDeploymentInputsModalPopup = function(deployment) {
+    var modalInstance = $modal.open({
+      templateUrl : 'inventory_deployment_inputs_view_popup.html',
+      controller : 'deploymentInputsViewCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve : {
+        message : function() {
+          var dataForPopup = {
+              deployment : deployment
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+      // No response.
+    });
+  };
+
+  /**
+   * Shows a modal pop-up to initiate update blueprint for a deployment
+   */
+  $scope.ecdapp.updateDeploymentModalPopup = function(deployment) {
+    var modalInstance = $modal.open({
+      templateUrl: 'inventory_deployment_update_popup.html',
+      controller: 'deploymentUpdateCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve: {
+        message: function() {
+          var dataForPopup = {
+              deployment : deployment
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+      if (response != null) {
+        if (response.error != null) {
+          $log.error('updateDeploymentModalPopup failed: ' + response.error);
+          alert('Failed to update deployment:\n' + response.error);
+        }
+        else {
+          $scope.ecdapp.viewDeploymentExecutionsModalPopup(deployment);
+        }
+      }
+    });
+  };
+
+  /**
+   * Shows a modal pop-up with blueprint content.
+   * Passes data in via an object named "message". 
+   */
+  $scope.ecdapp.getBlueprintDataModal = function(deployment) {
+    var modalInstance = $modal.open({
+      templateUrl : 'blueprint_content_popup.html',
+      controller : 'deployBlueprintContentCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve : {
+        message : function() {
+          var dataForPopup = {
+              blueprint : deployment,
+              tenant_name: $scope.ecdapp.selectedTenant
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+    });
+  };
+
+  
        /**
         * Shows a modal pop-up to create an execution from a deployment. 
         * Passes data in via an object named "message". 
@@ -96,7 +711,7 @@ appDS2.controller('deploymentTableController', function(
                        resolve : {
                                message : function() {
                                        var dataForPopup = {
-                                               deployment : deployment
+                                               deployment : deployment,
                                        };
                                        return dataForPopup;
                                }
@@ -119,253 +734,1480 @@ appDS2.controller('deploymentTableController', function(
                });
        };
        
-       /**
-        * Shows a modal pop-up to confirm deletion. 
-        * On successful completion, updates the table.
-        */
-       $scope.ecdapp.deleteDeploymentModalPopup = function(deployment) {               
-               var modalInstance = $modal.open({
-                       templateUrl : 'deployment_delete_popup.html',
-                       controller : 'deploymentDeleteCtrl',
-                       sizeClass: 'modal-small',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               deployment : deployment
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       if (debug)
-                               $log.debug('deleteDeploymentPopup: response: ' + JSON.stringify(response));
-                       if (response == null) {
-                               // $log.debug('user closed dialog');
-                       }
-                       else {
-                               if (response.error != null) {
-                                       $log.error('deleteDeploymentModalPopup failed: ' + response.error);
-                                       alert('Failed to delete deployment:\n' + response.error);
-                               }
-                               else {
-                                       // success, get the updated list.
-                                       $scope.ecdapp.loadTable()
-                               }
-                       }
-               });
-       };
+  $scope.ecdapp.checkHelmStatus = function(deployment) {
+    var selTenant = deployment.tenant_name;
+    if ( typeof selTenant === "undefined" ) {
+      selTenant = "default_tenant";
+    }
+    deployment.onlyLatest = true;
+
+    // This object holds data for this operation
+    $scope.ecdapp.helmStatusRequest = {
+        "deployment_id": deployment.id,
+        "workflow_name": "status",
+        "tenant": selTenant
+    };
+    InventoryDeploymentService.helmStatusFlow($scope.ecdapp.helmStatusRequest).then(function(jsonObj) {
+      if (debug)
+        $log.debug("checkHelmStatus response: " + JSON.stringify(jsonObj));
+      if (jsonObj.error) {
+        $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error;
+        $scope.ecdapp.updatingDeployment = false;
+        $scope.ecdapp.isDataLoading = false;
+        alert('Request Failed: ' + jsonObj.error);
+      } else {
+        console.log('%c POSTED helm status request', 'color: magenta; font-weight: bold;');
+        $scope.ecdapp.viewDeploymentExecutionsModalPopup(deployment);
+      }
+    }, function(error) {
+      $log.error('helmStatusFlow failed: ' + error);
+      alert('helmStatusFlow failed: ' + error);
+    });
+
+  };
+  
+  /**
+   * Shows a modal pop-up to initiate helm upgrade for a deployment
+   */
+  $scope.ecdapp.upgradeDeploymentModalPopup = function(deployment) {
+    //console.log(deployment);
+    var modalInstance = $modal.open({
+      templateUrl: 'inventory_deployment_upgrade_popup.html',
+      controller: 'deploymentUpgradeCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve: {
+        message: function() {
+          var dataForPopup = {
+              deployment : deployment
+          };
+          return dataForPopup;
+        }
+      }
+    });
+  };
+
+  /**
+   * Shows a modal pop-up to initiate helm rollback for a deployment
+   */
+  $scope.ecdapp.rollbackDeploymentModalPopup = function(deployment) {
+    var modalInstance = $modal.open({
+      templateUrl: 'inventory_deployment_rollback_popup.html',
+      controller: 'deploymentRollbackCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve: {
+        message: function() {
+          var dataForPopup = {
+              deployment : deployment
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+      // No response.
+    });
+  };
 
+  $scope.$on('$destroy', function() {
+    // Make sure that the interval is destroyed too
+    $scope.ecdapp.stopLoading();
+  });
+  
 });
 
 /*************************************************************************/
 
 appDS2.controller('deploymentDeleteCtrl', function(
-               $scope, $log, $modalInstance, message, DeploymentService) {
+    $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) {
 
-       'use strict';
-       
-       // Controls logging in this controller
-       var debug = false;
+  'use strict';
 
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'Delete Deployment';
-       $scope.ecdapp.deploymentId = message.deployment.id;
-       $scope.ecdapp.ignoreLiveNodes = false;
-
-       $scope.ecdapp.deleteDeploymentById = function(){
-               DeploymentService.deleteDeployment($scope.ecdapp.deploymentId, $scope.ecdapp.ignoreLiveNodes).then(
-                       function(response) {
-                               if (debug)
-                                       $log.debug('deploymentDeleteCtrl.deleteDeployment: ' + JSON.stringify(response));
-                               if (response && response.error) {
-                                       $log.error('DeploymentService.deleteDeployment failed: ' + response.error);
-                                       alert('Failed to delete deployment:\n' + response.error);
-                               }
-                               else {
-                                       // Delete service returns null on success.
-                                       $modalInstance.close("success");
-                               }
-                       },
-                       function(error) {
-                               $log.error('DeploymentService.deleteDeployment failed: ' + error);
-                               alert('Service failed to delete deployment:\n' + error);
-                       });
-       }
+  // Controls logging in this controller
+  var debug = false;
+
+  // this object holds all app data and functions
+  $scope.ecdapp = {};
+  $scope.ecdapp.label = 'Undeploy?';
+  $scope.ecdapp.deploymentRef = message.deployment.id;
+  var selTenant = message.deployment.tenant_name;
+  $scope.ecdapp.ui_tenant = selTenant;
+  $scope.ecdapp.tenant = selTenant;
+
+  $scope.ecdapp.deleteDeploymentById = function(){
+    $scope.ecdapp.isDisabled = true;
+    InventoryDeploymentService.deleteDeployment($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(
+        function(response) {
+          if (debug)
+            $log.debug('inventoryDeploymentDeleteCtrl.deleteDeployment: ' + JSON.stringify(response));
+          if (response && response.error) {
+            $log.error('InventoryDeploymentService.deleteDeployment failed: ' + response.error);
+            alert('Failed to delete deployment:\n' + response.error);
+          }
+          else {
+            // Delete service returns null on success.
+            $modalInstance.close("success");
+          }
+        },
+        function(error) {
+          $log.error('InventoryDeploymentService.deleteDeployment failed: ' + error);
+          alert('Service failed to delete deployment:\n' + error);
+        });
+  }
 
 });
 
 /*************************************************************************/
 
-appDS2.controller('deploymentExecuteCtrl', function(
-               $scope, $log, $modalInstance, message, ExecutionService) {
+appDS2.controller('deploymentExecutionsViewCtrl', function(
+    $scope, $rootScope, $interval, $log, $modalInstance, message, modalService, InventoryExecutionService, ExecutionService) {
 
-       'use strict';
-       
-       // Controls logging in this controller
-       var debug = false;
+  'use strict';
 
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'Execute Deployment';
-               
-       // Cache the input parameter names for validation
-       $scope.ecdapp.inputsDict = {};
-       if (debug)
-               $log.debug('DeploymentXeqCtrl: inputsDict is ' + JSON.stringify($scope.ecdapp.inputsDict));
-
-       // Copy the input names and values
-       // (different structure than blueprint)
-       /*for (var pkey in message.deployment.inputs) {
-               let dval = message.deployment.inputs[pkey];
-               inputsAndValues[pkey] = dval;
-       }*/
-
-       // Gather workflow names as a simple list
-       var workflowList = [];
-       for (var i = 0; i < message.deployment.workflows.length; i++)
-               workflowList.push(message.deployment.workflows[i].name);
-       if (debug)
-               $log.debug('DeploymentXeqCtrl: workflowList is ' + JSON.stringify(workflowList));
-
-       // Create an object for edit.
-       $scope.ecdapp.editRequest = {
-               deployment_id : message.deployment.id,
-               allow_custom_parameter : false,
-               force : false,
-               // Has title and value objects
-               workflow_name: { value : '' },
-               workflow_list : workflowList,
-               fileModel : null,
-               parmFileDict : {}
-       };
-       
-       $scope.selectWorkflowName = function(){
-               var workflows = message.deployment.workflows;
-               let inputsAndValues = {};
-               var res = workflows.filter(function(d){ 
-                       if(d.name == $scope.ecdapp.editRequest.workflow_name.value){ 
-                               return d 
-                               } 
-                       });
-               for(var key in res[0].parameters){
-                       inputsAndValues[key] = typeof (res[0].parameters[key].default) === 'string' ? res[0].parameters[key].default : null;
-               }
-               $scope.ecdapp.inputsDict = inputsAndValues;
-               $scope.ecdapp.editRequest.parmFileDict = inputsAndValues;
-       };
-               
-       if (debug)
-               $log.debug('DeploymentXeqCtrl: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest));
+  var debug = false;
 
-       /**
-        * Handler for file-read event reads file, parses YAML, validates content.
-        */
-       var fileReader = new FileReader();
-       fileReader.onload = function(event) {
-               let yamlString = fileReader.result;
-               if (debug)
-                       $log.debug('fileReader.onload: read: ' + yamlString);
-               let ydict = {};
-               try {
-                       ydict = YAML.parse(yamlString);
-               }
-               catch (ex) {
-                       alert('Failed to parse file as YAML:\n' + ex);
-               }
-               for (var ykey in ydict) {
-                       let yval = ydict[ykey];
-                       if (debug)
-                               $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey);
-                       // Only accept valid, expected key-value pairs
-                       if (typeof yval !== 'string' && typeof yval!=='number')
-                               alert('Unexpected file content:\nNot a simple key-value pair:\n' + ykey);
-                       else if (! (ykey in $scope.ecdapp.editRequest.parmFileDict))
-                               alert('Unexpected file content:\nKey not defined by deployment:\n' + ykey);
-                       else
-                               $scope.ecdapp.editRequest.parmFileDict[ykey] = yval;
-               }
-               if (debug)
-                       $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict));
-
-               // Update table in all cases 
-               $scope.$apply();
-       }
+  if (debug)
+    $log.debug("inventoryDeploymentsExecutionsViewCtrl.message: " + JSON.stringify(message));
 
-       // Handler for file-select event
-       $scope.handleFileSelect = function() {
-               if (debug)
-                       $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name);
-               fileReader.readAsText($scope.ecdapp.editRequest.fileModel);
-       };
+  // this object holds all app data and functions
+  $scope.ecdapp = {};
+  // models for controls on screen
+  $scope.ecdapp.label = 'Deployment ' + message.deployment.id + ' Executions';
+  $scope.ecdapp.tableData = [];
+  $scope.ecdapp.logTableData = [];
+  $scope.ecdapp.currentPageNum = 1;
+  $scope.ecdapp.viewPerPage = 10;
+  $scope.ecdapp.currentLogPageNum = 1;
+  $scope.ecdapp.selectedRow = null;
 
-       /**
-        * Validates content of user-editable fields.
-        * Returns null if all is well, 
-        * a descriptive error message otherwise.
-        */
-       var validateRequest = function(editRequest) {
-               if (debug)
-                       $log.debug('validateRequest: editRequest is ' + JSON.stringify(editRequest));
-               if (editRequest == null)
-                       return "No data found.\nPlease enter some values.";
-               if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '')
-                       return "Deployment ID is required.\nPlease enter a value.";
-               if (editRequest.workflow_name.value == null || editRequest.workflow_name.value.trim() == '')
-                       return "Workflow name is required.\nPlease select a workflow.";
-               // Check that every file parameter is defined by blueprint
-               for (var pkey in $scope.ecdapp.editRequest.parmFileDict) {
-                       // Defined in blueprint?
-                       if (! $scope.ecdapp.inputsDict[pkey]) 
-                               return 'Unexpected input parameter\n' + pkey;
-                       // Populated?
-                       let parmVal = $scope.ecdapp.editRequest.parmFileDict[pkey];
-                       if (parmVal.trim().length == 0)
-                               return 'Missing value for parameter ' + pkey;
-               }
-               // Check that a value is supplied for every expected input
-               for (var bkey in $scope.ecdapp.inputsDict) {
-                       if (! $scope.ecdapp.editRequest.parmFileDict[bkey]) 
-                               return 'Missing input parameter\n' + bkey;
-               }
-               return null;
-       }
-       
-       $scope.ecdapp.executeDeployment = function(editRequest) {
-               var validateMsg = validateRequest(editRequest);
-               if (validateMsg != null) {
-                       alert('Invalid execution request:\n' + validateMsg);
-                       return;                 
-               }
-
-               // Create request with key:value parameters dictionary
-               let executeRequest =    {
-                       deployment_id : editRequest.deployment_id, 
-                       workflow_name : editRequest.workflow_name.value,
-                       allow_custom_parameter : editRequest.allow_custom_parameter,
-                       force : editRequest.force,
-                       parameters : {}
-               };
-               for (var pkey in $scope.ecdapp.editRequest.parmFileDict) 
-                       executeRequest.parameters[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey];
-               if (debug) 
-                       $log.debug('executeDeployment: executeRequest is ' + JSON.stringify(executeRequest));
-
-               ExecutionService.executeDeployment(executeRequest)
-                       .then(function(response) {
-                               if (response.error)
-                                       alert('Failed to create execution:\n' + response.error);
-                               else    
-                                       $modalInstance.close(response);
-                       },
-                       function (error) {
-                               $log.error('deploymentExecuteCtrl: error while creating execution: ' + error);
-                               alert('Server rejected execute request:\n' + error);
-                       }
-               );
+  // other
+  $scope.ecdapp.errMsg = null;
+  $scope.ecdapp.isDataLoading = true;
+  $scope.ecdapp.isEventLogQuery = false;
+  $scope.ecdapp.isRequestFailed = false;
+  $scope.ecdapp.isLastExecution = message.deployment.onlyLatest;
+  $scope.ecdapp.isLogType = true;
+  $scope.ecdapp.refresh_switch = {
+      value: true
+  };
+  $scope.ecdapp.options = {
+      "on":"On",
+      "off":"Off"
+  }   
+  var selTenant = message.deployment.tenant_name;
 
-       };
+  $scope.ecdapp.ui_tenant = selTenant;
+  $scope.ecdapp.tenant = selTenant;
+  $scope.ecdapp.execId = "";
+  $scope.ecdapp.deplRef = message.deployment.id;
+  var stop;
+  /**
+   * Loads the table. Interprets the remote controller's response and copies
+   * to scope variables. The response is either a list to be assigned to
+   * tableData, or an error to be shown.
+   */
+  $scope.ecdapp.loadTable = function() {
+    $scope.ecdapp.isDataLoading = true;
+    InventoryExecutionService.getExecutionsByDeployment($scope.ecdapp.deplRef, 
+        $scope.ecdapp.tenant,
+        $scope.ecdapp.currentPageNum,
+        $scope.ecdapp.viewPerPage).then(
+            function(jsonObj) {
+              if (jsonObj.error) {
+                $log.error("deploymentExecutionsViewCtrl.loadTable failed: "
+                    + jsonObj.error);
+                $scope.ecdapp.isRequestFailed = true;
+                if (jsonObj.error.includes("404")) {
+                  $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!";
+                }
+                $scope.ecdapp.tableData = [];
+                $scope.ecdapp.stopLoading();
+              } else {
+                $scope.ecdapp.isRequestFailed = false;
+                $scope.ecdapp.errMsg = null;
+                $scope.ecdapp.totalPages = jsonObj.totalPages;
+                var resultLen = jsonObj.items.length;
+                if (resultLen != undefined && resultLen > 0) {
+                  var exec_id = jsonObj.items[resultLen-1].id;
+                      $scope.ecdapp.execId = exec_id;
+                      $scope.ecdapp.selectedRow = resultLen-1;
+                  if ($scope.ecdapp.isLastExecution) {
+                    $scope.ecdapp.tableData = [];
+                    $scope.ecdapp.tableData.push(jsonObj.items[resultLen-1]);
+                  } else {
+                    $scope.ecdapp.tableData = jsonObj.items;
+                  }
+                  $scope.ecdapp.getExecutionLogs($scope.ecdapp.selectedRow, exec_id, $scope.ecdapp.tenant);
+                }
+              }
+              $scope.ecdapp.isDataLoading = false;
+            },
+            function(error) {
+              $log.error("inventoryDeploymentExecutionsViewCtrl.loadTable failed: "
+                  + error);
+              $scope.ecdapp.isRequestFailed = true;
+              $scope.ecdapp.errMsg = error;
+              $scope.ecdapp.tableData = [];
+              $scope.ecdapp.isDataLoading = false;
+              $scope.ecdapp.stopLoading();
+            });
+  };
+  $scope.$watch('ecdapp.refresh_switch["value"]', function(newValue,oldValue,scope) {
+    if (newValue != oldValue) {
+      if (newValue === true) {
+        $scope.ecdapp.loadTable();
+        stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 30000, 100, false);
+      } else {
+        $scope.ecdapp.stopLoading();
+      }
+    }
+  }, true);
+
+  if ($scope.ecdapp.refresh_switch.value === true) {
+    stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 30000, 100, false);
+  }
+
+  $scope.ecdapp.stopLoading = function() {
+    if (angular.isDefined(stop)) {
+      $interval.cancel(stop);
+      stop = undefined;
+    }
+  };
 
+    $scope.ecdapp.copyStringToClipboard = function(str) {
+       // Create new element
+       var el = document.createElement('textarea');
+       // Set value (string to be copied)
+       el.value = str;
+       // Set non-editable to avoid focus and move outside of view
+       el.setAttribute('readonly', '');
+       el.style = {position: 'absolute', left: '-9999px'};
+       document.body.appendChild(el);
+       // Select text inside element
+       el.select();
+       // Copy text to clipboard
+       document.execCommand('copy');
+       // Remove temporary element
+       document.body.removeChild(el);
+    };
+
+  $scope.ecdapp.cancelExecutionModalPopup = function(execution, tenant) {
+    modalService.popupConfirmWin("Confirm", "Cancel execution with ID '"
+        + execution.id + "'?", function() {
+      $scope.ecdapp.isCancelOn = true;
+      // TODO: gather action from user
+      InventoryExecutionService.cancelExecution(execution.id, execution.deployment_id, "force-cancel", tenant).then(
+          function(response) {
+            if (debug)
+              $log.debug("Controller.cancelExecutionModalPopup: " + JSON.stringify(response));
+            if (response && response.error) {
+              // $log.error('cancelExectuion failed: ' + response.error);
+              alert('Failed to cancel execution:\n' + response.error);
+              $scope.ecdapp.isCancelOn = false;
+            }
+            else {
+              // No response body on success.
+              $scope.ecdapp.isCancelOn = false;
+              $scope.ecdapp.loadTable();
+            }
+          },
+          function(error) {
+            $scope.ecdapp.isCancelOn = false;
+            $log.error('ExecutionService.cancelExecution failed: ' + error);
+            alert('Service failed to cancel execution:\n' + error);
+          });
+    })
+  };
+
+  /**
+   * Invoked at first page load AND when
+   * user clicks on the B2B pagination control.
+   */
+  $scope.pageChangeHandler = function(page) {
+    if (debug)
+      console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page);
+    $scope.ecdapp.currentPageNum = page;
+    $scope.ecdapp.loadTable();
+
+  }
+  $scope.pageChangeHandlerEvent = function(page) {
+    if (debug)
+      console.log('pageChangeHandlerEvent: current is ' + $scope.ecdapp.currentLogPageNum + ' new is ' + page);
+      if (page != $scope.ecdapp.currentLogPageNum ) {
+      $scope.ecdapp.currentLogPageNum = page;
+      $scope.ecdapp.getExecutionLogs($scope.ecdapp.selectedRow, $scope.ecdapp.execId, $scope.ecdapp.tenant);
+    }
+  }
+
+  $scope.ecdapp.setClickedRow = function(index){  //function that sets the value of selectedRow to current index
+     $scope.ecdapp.selectedRow = index;
+  }
+  $scope.ecdapp.selected = false;
+  $scope.ecdapp.toggleStatusDefinitions = function() {
+    $scope.ecdapp.selected = $scope.ecdapp.selected ? false :true;
+  }
+
+  /**
+   * Shows a modal pop-up with the error.
+   */
+  $scope.ecdapp.viewErrorModalPopup = function(row) {
+    $modalInstance.dismiss('cancel');
+    modalService.showFailure('Error Details', row.error, function() { } );
+  };
+
+  $scope.ecdapp.getExecutionLogs = function(rowIdx, id, tenant) {
+    $scope.ecdapp.setClickedRow(rowIdx);
+    $scope.ecdapp.execId = id;
+    $scope.ecdapp.isEventLogQuery = false;
+    InventoryExecutionService.getEventsByExecution(id , $scope.ecdapp.isLogType, tenant,
+        $scope.ecdapp.currentLogPageNum, $scope.ecdapp.viewPerPage ).then(
+            function(jsonObj) {
+              if (jsonObj.error) {
+                $log.error("inventoryDeploymentExecutionsViewCtrl.getExecutionLogs failed: "
+                    + jsonObj.error);
+                $scope.ecdapp.isEventLogQuery = false;
+                $scope.ecdapp.evtErrMsg = jsonObj.error;
+                $scope.ecdapp.logTableData = [];
+              } else {
+                $scope.ecdapp.isEventLogQuery = true;
+                $scope.ecdapp.evtErrMsg = null;
+                $scope.ecdapp.totalLogPages = jsonObj.totalPages;
+                $scope.ecdapp.logTableData = jsonObj.items;
+              }
+              $scope.ecdapp.isDataLoading = false;
+            },
+            function(error) {
+              $log.error("inventoryDeploymentExecutionsViewCtrl.getExecutionLogs failed: "
+                  + error);
+              $scope.ecdapp.evtErrMsg = error;
+              $scope.ecdapp.logTableData = [];
+              $scope.ecdapp.isDataLoading = false;
+            });
+  }
+
+  $scope.$on('$destroy', function() {
+    // Make sure that the interval is destroyed too
+    $scope.ecdapp.stopLoading();
+  });
+});
+
+
+/*************************************************************************/
+appDS2.controller('deploymentInputsViewCtrl', function(
+    $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) {
+
+  'use strict';
+
+  // Controls logging in this controller
+  var debug = false;
+
+  // this object holds all app data and functions
+  $scope.ecdapp = {};
+  $scope.ecdapp.label = 'Deployment Inputs';
+  $scope.ecdapp.deploymentRef = message.deployment.id;
+  $scope.ecdapp.serviceId = message.deployment.serviceId;
+  $scope.ecdapp.errMsg = null;
+  $scope.ecdapp.isDataLoading = true;
+  $scope.ecdapp.isRequestFailed = false;
+  var selTenant = message.deployment.tenant_name;
+  if ( typeof selTenant === "undefined" ) {
+    selTenant = "default_tenant";
+  }
+  $scope.ecdapp.ui_tenant = selTenant;
+  $scope.ecdapp.tenant = selTenant;
+  let inputsAndDescriptions = {};
+  let inputsAndDefaults = {};
+  // Get associated blueprint for inputs info
+  InventoryDeploymentService.getBlueprint($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(blueprint) {
+    if (debug)
+      $log.debug("inventoryDeploymentInputsViewCtrl.getBlueprint response: " + JSON.stringify(blueprint));
+    if  (!blueprint.error) {
+      for (var pkey in blueprint.items[0].plan.inputs) {
+        let description = blueprint.items[0].plan.inputs[pkey].description;
+        if (  typeof description === "undefined" ) {
+          description = '';
+        }
+        inputsAndDescriptions[pkey] = description;
+      }
+      $scope.ecdapp.deployment.descriptionDict = inputsAndDescriptions;
+    }
+  },
+  function(error) {
+    $log.error('InventoryDeploymentService.getBlueprint failed: ' + JSON.stringify(error));
+  }); 
+      
+  InventoryDeploymentService.getDeployment($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) {
+    if (deployment.items.length == 0) {
+      $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!";
+      $log.error("InventoryDeploymentSerice.getDeployment failed: "
+          + $scope.ecdapp.errMsg);
+      $scope.ecdapp.isRequestFailed = true;
+    } 
+    // Deployment IDs are unique, so this will always return exactly one item!
+    // retrieve blueprintId and inputs of deployment.
+    else {
+      $scope.ecdapp.errMsg = null;
+      //$scope.ecdapp.deployment = deployment.items[0];
+      let ydict = deployment.items[0].inputs; 
+      for (var ykey in ydict) { 
+        let yval = ydict[ykey]; 
+        if (yval.constructor === {}.constructor) 
+          inputsAndDefaults[ykey] = JSON.stringify(yval, undefined, 2);
+        else 
+          inputsAndDefaults[ykey] = yval;
+      }
+      $scope.ecdapp.isRequestFailed = false;
+    }
+    $scope.ecdapp.isDataLoading = false;
+  },
+  function(error) {
+    $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error));
+    $scope.ecdapp.isRequestFailed = true;
+    $scope.ecdapp.errMsg = error;
+    $scope.ecdapp.isDataLoading = false;
+  }); 
+  $scope.ecdapp.deployment = {
+      parmFileDict : inputsAndDefaults,
+      descriptionDict : inputsAndDescriptions
+  };
 });
 
+/*************************************************************************/
+
+appDS2.controller('deployBlueprintContentCtrl', function(
+    $scope, $log, message, DeploymentService) {
+
+  'use strict';
+
+  var debug = false;
+
+  if (debug)
+    $log.debug("deployBlueprintContentCtrl.message: " + JSON.stringify(message));
+
+  // this object holds all app data and functions
+  $scope.ecdapp = {};
+  $scope.ecdapp.label = 'View Blueprint ' + message.blueprint.blueprint_id;
+  // Fetch the blueprint
+  $scope.ecdapp.isDataLoading = true;
+  DeploymentService.getBlueprintContent(message.blueprint.blueprint_id, message.tenant_name).then(function(jsonObj) {
+    if (debug)
+      $log.debug("deployBlueprintContentCtrl.viewBlueprint response: " + JSON.stringify(jsonObj));
+    if (jsonObj.error) {
+      $scope.ecdapp.errMsg = 'Request Failed';
+    }
+    else {
+      $scope.ecdapp.typeName = message.blueprint.blueprint_id;
+      $scope.ecdapp.blueprint = jsonObj.data;
+    }
+    $scope.ecdapp.isDataLoading = false;
+  }, function(error) {
+    $scope.ecdapp.isDataLoading = false;
+    alert('Failed to get blueprint. Please retry.');
+    $log.error("deployBlueprintContentCtrl failed: " + error);
+  });
+});
+
+
+       /*************************************************************************/
+       appDS2.controller('deploymentUpdateCtrl', function(
+           $scope, $log, $modalInstance, message, InventoryBlueprintService, InventoryDeploymentService) {
+
+         'use strict';
+
+         var debug = false;
+         if (debug)
+           $log.debug("inventoryDeploymentUpdateCtrl.message: " + JSON.stringify(message));
+
+         // this object holds all app data and functions
+         $scope.ecdapp = {};
+         $scope.ecdapp.deploymentInProgress = false;
+         $scope.ecdapp.serviceTypeComplete = false;
+         $scope.ecdapp.isDataLoading = true;
+         $scope.ecdapp.errMsg = null;
+         $scope.ecdapp.label = 'Update ' + message.deployment.id;
+         $scope.ecdapp.deploymentRef = message.deployment.id;
+         var selTenant = message.deployment.tenant_name;
+         if ( typeof selTenant === "undefined" ) {
+           selTenant = "default_tenant";
+         }
+         $scope.ecdapp.tenant = selTenant;
+         $scope.ecdapp.ui_tenant = selTenant;
+         $scope.ecdapp.updateBp = '';
+         $scope.ecdapp.typeName = '';
+         $scope.ecdapp.typeId = '';
+         $scope.ecdapp.inputsDict = {};
+         $scope.ecdapp.nodeInst = [];
+         $scope.ecdapp.selectedNodeInst;
+         $scope.ecdapp.editRequest = {
+             deployment_id : $scope.ecdapp.deploymentRef,
+             type_id : '',
+             fileModel : null,
+             parmFileDict : {},
+             descriptionDict : {},
+             tenant : $scope.ecdapp.tenant
+         };
+         $scope.ecdapp.install_flow = {
+             value: true
+         };
+           
+         $scope.ecdapp.uninstall_flow = {
+             value: true
+         };
+         
+         $scope.ecdapp.reinstall_flow = {
+             value: true
+         };
+         
+         $scope.ecdapp.install_first_flow_flag = {
+             value: false
+         };
+         
+         $scope.ecdapp.force_flag = {
+             value: false
+         };
+         
+         $scope.ecdapp.ignore_failure_flag = {
+             value: false
+         };
+
+         $scope.ecdapp.skip_install = false;
+         $scope.ecdapp.skip_uninstall = false;
+         $scope.ecdapp.skip_reinstall = false;
+         $scope.ecdapp.install_first_flow = false;
+         $scope.ecdapp.force = false;
+         $scope.ecdapp.ignore_failure = false;
+         
+         $scope.$watch('ecdapp.install_flow["value"]', function(newValue,oldValue,scope) {
+           if (newValue != oldValue) {
+             console.log("toggled install flow: " + newValue);
+             $scope.ecdapp.skip_install = oldValue;
+           }
+         }, true);
+         
+         $scope.$watch('ecdapp.uninstall_flow["value"]', function(newValue,oldValue,scope) {
+           if (newValue != oldValue) {
+             console.log("toggled uninstall flow: " + newValue);
+             $scope.ecdapp.skip_uninstall = oldValue;
+           }
+         }, true);
+         
+         $scope.$watch('ecdapp.reinstall_flow["value"]', function(newValue,oldValue,scope) {
+           if (newValue != oldValue) {
+             console.log("toggled reinstall flow: " + newValue);
+             $scope.ecdapp.skip_reinstall = oldValue;
+           }
+         }, true);
+         
+         $scope.$watch('ecdapp.install_first_flow_flag["value"]', function(newValue,oldValue,scope) {
+           if (newValue != oldValue) {
+             console.log("toggled install first flow: " + newValue);
+             $scope.ecdapp.install_first_flow = newValue;
+           }
+         }, true);
+         
+         $scope.$watch('ecdapp.force_flag["value"]', function(newValue,oldValue,scope) {
+           if (newValue != oldValue) {
+             console.log("toggled force flag: " + newValue);
+             $scope.ecdapp.force = newValue;
+           }
+         }, true);
+         
+         $scope.$watch('ecdapp.ignore_failure_flag["value"]', function(newValue,oldValue,scope) {
+           if (newValue != oldValue) {
+             console.log("toggled ignore_failure flow: " + newValue);
+             $scope.ecdapp.ignore_failure = newValue;
+           }
+         }, true);
+
+         // deployment node instances
+         InventoryDeploymentService.getNodeInstances($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant)
+         .then(function(jsonObj) {
+           if (jsonObj.error) {
+             $log.error("inventoryDeploymentUpdateCtrl.getNodeInstances failed: " + jsonObj.error);
+             $scope.ecdapp.errMsg = jsonObj.error;
+             $scope.ecdapp.nodeInst = [];
+           } else {
+             $scope.ecdapp.errMsg = null;
+             for (var nodeIndx = 0; nodeIndx < jsonObj.items.length; nodeIndx++) {
+               $scope.ecdapp.nodeInst.push(jsonObj.items[nodeIndx].id);
+             }
+           }     
+         }, function(error) {
+           $log.error("inventoryDeploymentUpdateCtrl.getNodeInstances failed: " + error);
+           $scope.ecdapp.errMsg = error;
+           $scope.ecdapp.nodeInst = [];
+           $scope.ecdapp.isDataLoading = false;
+         });    
+
+         // current blueprint
+/*       var typeLink = message.deployment.typeLink.href;
+         var n = typeLink.lastIndexOf("/");
+         var typeId = typeLink.substring(n+1);
+         // Fetch the blueprint
+         $scope.ecdapp.isDataLoading = true;
+         InventoryBlueprintService.viewBlueprint(typeId).then(function(jsonObj) {
+           if (debug)
+             $log.debug("inventoryDeploymentUpdateCtrl.viewBlueprint response: " + JSON.stringify(jsonObj));
+           if (jsonObj.error) {
+             $scope.ecdapp.errMsg = 'Request Failed';
+           }
+           else {
+             $scope.ecdapp.typeName = jsonObj.typeName;
+             $scope.ecdapp.typeId = jsonObj.typeId;
+             $scope.ecdapp.bp.push(jsonObj);
+             $scope.ecdapp.getBlueprint();
+           }
+           //$scope.ecdapp.isDataLoading = false;
+         }, function(error) {
+           $scope.ecdapp.isDataLoading = false;
+           alert('Failed to get blueprint. Please retry.');
+           $log.error("blueprintViewCtrl failed: " + error);
+         });*/
+
+         // get the blueprints from inventory matching deployment reference filter
+         $scope.ecdapp.bp = [];
+         InventoryBlueprintService.getBlueprintsSummary()
+         .then(function(jsonObj) {
+           if (jsonObj.error) {
+             $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + jsonObj.error);
+             $scope.ecdapp.errMsg = jsonObj.error;
+             $scope.ecdapp.bp = [];
+           } else {
+             $scope.ecdapp.errMsg = null;
+             $scope.ecdapp.bp = jsonObj;
+           }     
+           $scope.ecdapp.isDataLoading = false;
+         }, function(error) {
+           $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + error);
+           $scope.ecdapp.errMsg = error;
+           $scope.ecdapp.bp = [];
+           $scope.ecdapp.isDataLoading = false;
+         });
+         $scope.ecdapp.getBlueprint = function() {
+           $scope.ecdapp.isDataLoading = true;
+           InventoryBlueprintService.viewBlueprint($scope.ecdapp.typeId).then(function(jsonObj) {
+             if (debug)
+               $log.debug("inventoryDeploymentUpdateCtrl.viewBlueprint response: " + JSON.stringify(jsonObj));
+             if (jsonObj.error) {
+               $scope.ecdapp.errMsg = 'Request Failed';
+               $scope.ecdapp.serviceTypeComplete = false;
+               $scope.ecdapp.isDataLoading = false;
+             }
+             else {
+               $scope.ecdapp.typeName = jsonObj.typeName;
+               $scope.ecdapp.typeVersion = jsonObj.typeVersion;
+               $scope.ecdapp.inputsDict = jsonObj.blueprintInputs;
+               // query the current deployment inputs
+               InventoryDeploymentService.getDeployment($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) {
+                 if (deployment.items.length == 0) {
+                   $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!";
+                   $log.error("InventoryDeploymentSerice.getDeployment failed: "
+                       + $scope.ecdapp.errMsg);
+                   //$scope.ecdapp.isRequestFailed = true;
+                   $scope.ecdapp.serviceTypeComplete = true;
+                 } 
+                 // Deployment IDs are unique, so this will always return exactly one item!.
+                 // retrieve inputs of deployment.
+                 else {
+                   $scope.ecdapp.errMsg = null;
+                   $scope.ecdapp.deployment = deployment.items[0];
+                   // Copy the input parameter names and default values
+                   let inputsAndDefaults = {};
+                   let inputsAndDescriptions = {};
+                   let ydict = deployment.items[0].inputs; 
+                   for (var ykey in ydict) { 
+                     let yval = ydict[ykey]; 
+                     if (yval.constructor === {}.constructor) 
+                       inputsAndDefaults[ykey] = JSON.stringify(yval, undefined, 2);
+                     else 
+                       //$scope.ecdapp.deployment.inputs[ykey] = yval;
+                       inputsAndDefaults[ykey] = yval;
+                   }
+                   for (var pkey in $scope.ecdapp.inputsDict) {
+                     //$scope.ecdapp.deployment = deployment.items[0];           
+                     let description = $scope.ecdapp.inputsDict[pkey].description;
+                     if (  typeof description === "undefined" )
+                       description = '';
+                     inputsAndDescriptions[pkey] = description;            
+                   }
+                   
+                   $scope.ecdapp.editRequest.parmFileDict = inputsAndDefaults;
+                   $scope.ecdapp.editRequest.descriptionDict = inputsAndDescriptions;
+                   $scope.ecdapp.editRequest.type_id = $scope.ecdapp.typeId;
+                   if (debug)
+                     $log.debug('inventoryBlueprintDeployCtrl: inputsAndDefaults: ' + JSON.stringify(inputsAndDefaults));
+
+                   $scope.ecdapp.serviceTypeComplete = true;
+                   //$scope.$apply();
+                 }
+                 $scope.ecdapp.isDataLoading = false;
+               },
+               function(error) {
+                 $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error));
+                 $scope.ecdapp.isRequestFailed = true;
+                 $scope.ecdapp.errMsg = error;
+                 $scope.ecdapp.isDataLoading = false;
+               }); 
+             }
+             $scope.ecdapp.isDataLoading = false;
+           }, function(error) {
+             $scope.ecdapp.isDataLoading = false;
+             $scope.ecdapp.serviceTypeComplete = false;
+             alert('Failed to get blueprint. Please retry with valid blueprint ID.');
+             $log.error("inventoryDeploymentUpdateCtrl failed: " + error);
+           });
+         };
+
+         /**
+          * Handler for file-read event reads file, parses JSON, validates content.
+          */
+         var fileReader = new FileReader();
+         fileReader.onload = function(event) {
+           let jsonString = fileReader.result;
+           if (debug)
+             $log.debug('fileReader.onload: read: ' + jsonString);
+           let ydict = {};
+           try {
+             ydict = JSON.parse(jsonString);
+           }
+           catch (ex) {
+             alert('Failed to parse file as JSON:\n' + ex);
+           }
+           // Process the file
+           for (var ykey in ydict) {
+             let yval = ydict[ykey];
+             if (debug)
+               $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey);
+             // Allow only expected keys with scalar values
+             if (! (ykey in $scope.ecdapp.editRequest.parmFileDict))
+               alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey);
+             if (yval.constructor === {}.constructor)
+               $scope.ecdapp.editRequest.parmFileDict[ykey] = angular.toJson(yval);
+             else
+               $scope.ecdapp.editRequest.parmFileDict[ykey] = yval;
+           }
+           if (debug)
+             $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict));
+
+           // Update table in all cases 
+           $scope.$apply();
+         }
+
+         // Handler for file-select event
+         $scope.handleFileSelect = function() {
+           if (debug)
+             $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name);
+           fileReader.readAsText($scope.ecdapp.editRequest.fileModel);
+         };
+
+         $scope.ecdapp.validateRequest = function(editRequest) {
+           if (editRequest == null)
+             return 'No data found.\nPlease enter some values.';
+           if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '')
+             return 'Deployment ID is required.\nPlease enter a value.';
+           if (editRequest.type_id == null || editRequest.type_id.trim() == '')
+             return 'Type ID is required.\nPlease enter a value.';
+           // Check that every file parameter is defined by blueprint
+           for (var pkey in $scope.ecdapp.editRequest.parmFileDict) {
+             // Defined in blueprint?
+             if (! $scope.ecdapp.inputsDict[pkey]) 
+               return 'Unexpected input parameter\n' + pkey;
+           }
+           return null;
+         }
+
+         $scope.ecdapp.updateDeployment = function(editRequest) {
+           if (debug)
+             $log.debug('deployBlueprint: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest));
+           var validateMsg = $scope.ecdapp.validateRequest(editRequest);
+           if (validateMsg != null) {
+             alert('Invalid Request:\n' + validateMsg);
+             $scope.ecdapp.errMsg = validateMsg;
+             return;     
+           }
+           // Create request with key:value parameters dictionary
+           let deploymentRequestObject = {
+               deploymentId : editRequest.deployment_id,
+               serviceTypeId : editRequest.type_id,
+               inputs : {},
+               tenant : editRequest.tenant,
+               method : "update",
+               reinstall_list : $scope.ecdapp.selectedNodeInst,
+               skip_install : $scope.ecdapp.skip_install,
+               skip_uninstall : $scope.ecdapp.skip_uninstall,
+               skip_reinstall : $scope.ecdapp.skip_reinstall,
+               force : $scope.ecdapp.force,
+               ignore_failure : $scope.ecdapp.ignore_failure,
+               install_first : $scope.ecdapp.install_first_flow
+           };
+
+           for (var pkey in $scope.ecdapp.editRequest.parmFileDict)
+             try {
+               deploymentRequestObject.inputs[pkey] = angular.fromJson($scope.ecdapp.editRequest.parmFileDict[pkey]);
+             } catch (error) {
+               deploymentRequestObject.inputs[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey];
+             }
+             if (debug) 
+               $log.debug('deployBlueprint: deploymentRequestObject is ' + JSON.stringify(deployRequestObject));
+
+             $scope.ecdapp.deploymentInProgress = true;
+             InventoryDeploymentService.deployBlueprint(deploymentRequestObject)
+             .then(function(response) {
+               $scope.ecdapp.deploymentInProgress = false;
+               if (response.error) {
+                 alert('Failed to deploy blueprint:\n' + response.error);
+                 $scope.ecdapp.errMsg = response.error;
+               } else {
+                 alert('Deployment update request sent successfully, query the execution status for final outcome');
+                 $modalInstance.close(response);
+               }
+             },
+             function (error) {
+               $log.error('inventoryBlueprintDeployCtrl: error while deploying: ' + error);
+               alert('Server rejected deployment request:\n' + error);
+               $scope.ecdapp.deploymentInProgress = false;
+             }
+             );
+         };
+
+       });
+
+       /*************************************************************************/
+       appDS2.controller('deploymentRollbackCtrl', function(
+           $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) {
+
+         'use strict';
+
+         // Controls logging in this controller
+         var debug = false;
+
+         // this object holds all app data and functions
+         $scope.ecdapp = {};
+         $scope.ecdapp.label = 'Deployment Rollback';
+         $scope.ecdapp.revisions = [];
+         $scope.ecdapp.deploymentRef = message.deployment.id;   
+         $scope.ecdapp.serviceId = message.deployment.serviceId;
+         $scope.ecdapp.errMsg = null;
+         $scope.ecdapp.isDataLoading = true;
+         $scope.ecdapp.isRequestFailed = false;
+         $scope.ecdapp.updatingDeployment = false;
+         var selTenant = message.deployment.tenant_name;
+         if ( typeof selTenant === "undefined" ) {
+           selTenant = "default_tenant";
+         }
+         $scope.ecdapp.tenant = selTenant;
+         $scope.ecdapp.ui_tenant = selTenant;
+         $scope.ecdapp.local_revisions = [];
+         // This object holds data for this operation
+         $scope.ecdapp.rollbackRequest = {
+             "deployment_id": message.deployment.deploymentRef,
+             "workflow_name": "rollback",
+             "tenant": selTenant,
+             "revision": 1
+         };
+
+         InventoryDeploymentService.getNodeInstanceVersions($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(nodeRunTime) {
+           if (nodeRunTime == null) {
+             $scope.ecdapp.errMsg = "Failed to retrieve Node instance runtime information";
+             $log.error("InventoryDeploymentSerice.getNodeInstanceVersions failed: "
+                 + $scope.ecdapp.errMsg);
+             $scope.ecdapp.isRequestFailed = true;     
+           } else {
+             $scope.ecdapp.errMsg = null;
+             $scope.ecdapp.revisions = nodeRunTime.items[0].runtime_properties['helm-history'];
+             if (Array.isArray($scope.ecdapp.revisions) ) {
+               var dLen = $scope.ecdapp.revisions.length;
+
+               for (var i = 1; i < dLen; i++) {
+                 var str = $scope.ecdapp.revisions[i].replace(/\s+/g, ' ');
+                 var itemStrArr = str.split(" ");
+                 var itemLen = itemStrArr.length;
+                 var revObj = {};
+                 revObj.revision = itemStrArr[0].trim();
+                 revObj.updated = itemStrArr.slice(1,5).toString().replace(/,/g, ' '); 
+                 revObj.status = itemStrArr[6].trim();
+                 revObj.chart = itemStrArr[7].trim();
+                 revObj.description = itemStrArr.slice(8,itemLen).toString().replace(/,/g, ' ');
+                 revObj.name = itemStrArr[0].trim();
+                 revObj.checked = false;
+                 $scope.ecdapp.local_revisions.push(revObj);
+               }
+             }
+             console.log($scope.ecdapp.local_revisions);
+             $scope.ecdapp.isRequestFailed = false;
+           }
+           $scope.ecdapp.isDataLoading = false;
+         },
+         function(error) {
+           $log.error('InventoryDeploymentService.getNodeInstanceVersions failed: ' + JSON.stringify(error));
+           $scope.ecdapp.isRequestFailed = true;
+           $scope.ecdapp.errMsg = error;
+           $scope.ecdapp.isDataLoading = false;
+         });
+         $scope.ecdapp.updateSelection = function(position) {
+           $scope.ecdapp.rollbackRequest.revision = position;
+           angular.forEach($scope.ecdapp.local_revisions, function(item, index) {
+             if (position != index+1) 
+               item.checked = false;
+           });
+         }
+         /**
+          * rollback deployment based on parameters user enters/adjusts in modal popup
+          * First retrieves the node-id using the blueprintId
+          * Using the node-id and deploymentId, retrieves the node-instance-id
+          * Calls the update resource API, passing object with deploymentId, and changed parameters
+          */
+         $scope.ecdapp.rollbackWorkflow = function(revision) {
+           $scope.ecdapp.updatingDeployment = true;
+           $scope.ecdapp.isDataLoading = true;
+           InventoryDeploymentService.rollbackFlow($scope.ecdapp.rollbackRequest).then(function(jsonObj) {
+             if (debug)
+               $log.debug("inventoryDeploymentRollbackCtrl.rollbackWorkflow response: " + JSON.stringify(jsonObj));
+             if (jsonObj.error) {
+               $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error;
+               $scope.ecdapp.updatingDeployment = false;
+               $scope.ecdapp.isDataLoading = false;
+             } else {
+               console.log('%c ROLLBACK RESOURCES COMPLETED', 'color: magenta; font-weight: bold;');
+               alert('Rollback request for ' + $scope.ecdapp.deploymentRef + ' successfully went through to Cloudiy. Rollback is now pending');
+               $scope.ecdapp.updatingDeployment = false;
+               $scope.ecdapp.isDataLoading = false;
+             }
+           }, function(error) {
+             $scope.ecdapp.updatingDeployment = false;
+             $log.error('inventoryDeploymentRollbackCtrl failed: ' + error);
+             alert('Failed to rollback Deployment ' + $scope.ecdapp.deploymentRef + '. Please retry.');
+             $scope.ecdapp.isDataLoading = false;
+           });
+         }
+       });
+
+        /*************************************************************************/
+  appDS2.controller('appReconfigCtrl', function(
+      $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService, DeploymentService) {
+
+    'use strict';
+
+    var debug = true;
+    // this object holds all app data and functions
+    $scope.ecdapp = {};
+    $scope.ecdapp.tenant = message.deployment.tenant_name;
+    $scope.ecdapp.deploymentId = message.deployment.id;
+    $scope.ecdapp.bpId = message.deployment.blueprint_id;
+    $scope.ecdapp.errMsg = null;
+    $scope.ecdapp.isDataLoading = true;
+    $scope.ecdapp.isRequestFailed = false;
+    $scope.ecdapp.updatingDeployment = false;
+    $scope.ecdapp.parmFileDict = {};
+    $scope.ecdapp.parmCurrFileDict = {};
+    $scope.ecdapp.app_config_from_bp = {};
+    $scope.ecdapp.app_config_new = {};
+    $scope.ecdapp.app_config_bakup = {};
+    $scope.ecdapp.app_config_inputs = [];
+    $scope.ecdapp.app_config_bp_str ='';
+    $scope.ecdapp.app_config_latest_str ='';
+    $scope.ecdapp.descriptionDict = {};
+    $scope.ecdapp.appConfigOverride = {};
+    $scope.ecdapp.app_config_input_map = {};
+
+    $scope.ecdapp.reconfigRequest = {
+        deployment_id: $scope.ecdapp.deploymentId,
+        workflow_id: 'execute_operation',
+        parameters: {},
+        tenant: $scope.ecdapp.tenant
+    };
+    $scope.ecdapp.reconfigRequest.parameters.operation = 
+      'dcae.interfaces.lifecycle.Reconfiguration';
+    $scope.ecdapp.reconfigRequest.parameters.operation_kwargs = {};
+    $scope.ecdapp.reconfigRequest.parameters.operation_kwargs.type = 'app_reconfig';
+    $scope.ecdapp.reconfigRequest.parameters.operation_kwargs.application_config = {};
+    $scope.ecdapp.reconfigRequest.parameters.allow_kwargs_override = true;
+    $scope.ecdapp.reconfigRequest.parameters.type_names =
+      ['dcae.nodes.DockerContainerForComponents', 'dcae.nodes.DockerContainerForComponentsUsingDmaap',
+        'dcae.nodes.ContainerizedServiceComponent', 'dcae.nodes.ContainerizedServiceComponentUsingDmaap'];
+
+    // get the BP object from cloudify
+    // get the depl object from cloudify
+    // get the node instance data from cloudify
+    // parse the application_config from BP node properties
+    // parse the inputs from deployment
+    // display FORM with current input fields that are referred in the appl
+    // config object
+    // display application_config on the screen and setup data binding to the
+    // input FORM
+    // create POST request body for start execution to cloudify
+    // invoke service method to send POST request to cloudify
+    InventoryDeploymentService.getBlueprint($scope.ecdapp.bpId, 
+        $scope.ecdapp.tenant).then(function(blueprint) {
+          if (debug)
+            $log.debug("appReconfigCtrl.getBlueprint response: " + JSON.stringify(blueprint));
+          if  (blueprint.error) {
+            $scope.ecdapp.errMsg = 'Request Failed: ' + blueprint.error;
+            $scope.ecdapp.updatingDeployment = false;
+            $scope.ecdapp.isRequestFailed = true;
+          }
+          else {
+            $scope.ecdapp.isRequestFailed = false;
+            if (Array.isArray(blueprint.items) && blueprint.items.length > 0) {
+              var foundNode = blueprint.items[0].plan.nodes.find(function checkAppConfig(node) {
+                if (Object.keys(node.properties).includes("application_config")) {
+                  return true;
+                }
+              });
+              if (foundNode != undefined && foundNode.properties != undefined ) {
+                $scope.ecdapp.app_config_from_bp = foundNode.properties.application_config;
+                $scope.ecdapp.app_config_bp_str = 
+                  JSON.stringify($scope.ecdapp.app_config_from_bp, undefined, 4);
+
+                $scope.ecdapp.checkType = function(key1, value1) {
+                  if (value1 instanceof Object && !Array.isArray(value1)) {
+                    for (let [key2, value2] of Object.entries(value1)) {
+                      if (key2 == "get_input") {
+                        $scope.ecdapp.app_config_inputs.push(value2);
+                        $scope.ecdapp.app_config_input_map[key1] = value2;
+                      } else {
+                        $scope.ecdapp.checkType(key2, value2);
+                      }
+                    }
+                  }
+                };
+
+                for (let [key1, value1] of 
+                    Object.entries($scope.ecdapp.app_config_from_bp)) 
+                {
+                  $scope.ecdapp.checkType(key1, value1);
+                }
+              }
+
+              let inputsAndDescriptions = {};
+              for (var pkey in blueprint.items[0].plan.inputs) {
+                let description = blueprint.items[0].plan.inputs[pkey].description;
+                if (  typeof description === "undefined" ) {
+                  description = '';
+                }
+                inputsAndDescriptions[pkey] = description;
+              }
+              $scope.ecdapp.descriptionDict = inputsAndDescriptions;
+
+              InventoryDeploymentService.getDeployment($scope.ecdapp.deploymentId, 
+                  $scope.ecdapp.tenant).then(function(deployment) {
+                    if (deployment.items.length == 0) {
+                      $scope.ecdapp.errMsg = "404 - Deployment " + $scope.ecdapp.deploymentId + " Not Found!";
+                      $log.error("InventoryDeploymentSerice.getDeployment failed: "
+                          + $scope.ecdapp.errMsg);
+                      $scope.ecdapp.isRequestFailed = true;
+                    } 
+                    else {
+                      $scope.ecdapp.errMsg = null;
+                      $scope.ecdapp.deployment = deployment.items[0];
+                      $scope.ecdapp.isRequestFailed = false;
+                      if (Array.isArray(deployment.items) && deployment.items.length > 0) {
+                        var deplInputs = deployment.items[0].inputs;
+                        $scope.ecdapp.app_config_inputs.forEach(function findMatch(value, index, array) {
+                          for (let [key, val] of Object.entries(deplInputs)) {
+                            if (value == key) {
+                              $scope.ecdapp.parmFileDict[key] = val;
+                            }
+                          }
+                        });
+                      }
+                    }
+                    $scope.ecdapp.isDataLoading = false;
+                  },
+                  function(error) {
+                    $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error));
+                    $scope.ecdapp.isRequestFailed = true;
+                    $scope.ecdapp.errMsg = error;
+                    $scope.ecdapp.isDataLoading = false;
+                  });
+
+              InventoryDeploymentService.getNodeInstanceData($scope.ecdapp.deploymentId, 
+                  $scope.ecdapp.tenant).then(function(nodeInstances) {
+                    if (Array.isArray(nodeInstances.items) && nodeInstances.items.length > 0) {
+                      var foundNode = nodeInstances.items.find(function checkAppConfig(item) {
+                        if (Object.keys(item.runtime_properties).includes("application_config")) {
+                          return true;
+                        }
+                      });
+                      if (foundNode != undefined) {
+                        $scope.ecdapp.app_config_new = foundNode.runtime_properties.application_config;
+                        $scope.ecdapp.app_config_latest_str = 
+                          JSON.stringify($scope.ecdapp.app_config_new, undefined, 4);
+                        for (let [key, value] of 
+                            Object.entries(foundNode.runtime_properties.application_config)) 
+                        {
+                          if (value.constructor === {}.constructor)
+                            $scope.ecdapp.appConfigOverride[key] = angular.toJson(value);
+                          else
+                            $scope.ecdapp.appConfigOverride[key] = value;      
+                        }
+                        $scope.ecdapp.app_config_inputs.forEach(function findMatch(value, index, array) {
+                          for (let [key, val] of Object.entries($scope.ecdapp.appConfigOverride)) {
+                            if (value == key) {
+                              $scope.ecdapp.parmCurrFileDict[key] = val;
+                            }
+                          }
+                        });             
+                      }
+                    }
+                  },
+                  function(error) {
+                    $log.error('InventoryDeploymentService.getNodeInstances failed: ' + JSON.stringify(error));
+                  });
+            }
+            $scope.ecdapp.isDataLoading = false;
+          }
+        },
+        function(error) {
+          $log.error('InventoryDeploymentService.getBlueprint failed: ' + JSON.stringify(error));
+          $scope.ecdapp.isRequestFailed = true;
+          $scope.ecdapp.errMsg = error;
+          $scope.ecdapp.isDataLoading = false;
+        });   
+
+    $scope.ecdapp.refreshAppConfig = function(newInputs) {
+      angular.copy($scope.ecdapp.app_config_from_bp, $scope.ecdapp.app_config_bakup);
+      for (let [input_key, input_val] of Object.entries(newInputs)) {
+        $scope.ecdapp.replaceNewInput(input_key, input_val, $scope.ecdapp.app_config_from_bp);
+      }
+      angular.copy($scope.ecdapp.app_config_from_bp, $scope.ecdapp.app_config_new);
+      angular.copy($scope.ecdapp.app_config_bakup, $scope.ecdapp.app_config_from_bp);
+
+      $scope.ecdapp.app_config_latest_str = 
+        JSON.stringify($scope.ecdapp.app_config_new, undefined, 4);
+    };
+
+    var fileReader = new FileReader();
+    fileReader.onload = function(event) {
+      let jsonString = fileReader.result;
+      let ydict = {};
+      try {
+        ydict = JSON.parse(jsonString);
+      }
+      catch (ex) {
+        alert('Failed to parse file as JSON:\n' + ex);
+      }
+      // Process the file
+      for (var ykey in ydict) {
+        let yval = ydict[ykey];
+        // Allow only expected keys with scalar values
+        if (ykey in $scope.ecdapp.parmFileDict)
+        {
+          // alert('Unexpected file content:\nKey not defined by blueprint:\n' +
+          // ykey);
+          if (yval.constructor === {}.constructor)
+            $scope.ecdapp.parmFileDict[ykey] = angular.toJson(yval);
+          else
+            $scope.ecdapp.parmFileDict[ykey] = yval;
+        }
+      }
+      $scope.ecdapp.refreshAppConfig($scope.ecdapp.parmFileDict);
+      $scope.$apply();
+    };
+    // Handler for file-select event
+    $scope.handleFileSelect = function() {
+      if (debug)
+        $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name);
+      fileReader.readAsText($scope.ecdapp.editRequest.fileModel);
+    };
+    $scope.ecdapp.replaceNewInput = function(input_key, input_val, src) {
+      var itemFound = false;
+      for (let [key, value] of Object.entries(src)) {
+        if (value instanceof Object && !Array.isArray(value)) {
+          for (let [key2, value2] of Object.entries(value)) {
+            if (key2 == "get_input" && value2 == input_key) {
+              src[key] = input_val;
+              itemFound = true;
+              break;
+            } else {
+              $scope.ecdapp.replaceNewInput(input_key, input_val, value2);
+            }
+          }
+        } 
+        if (itemFound) {
+          break;
+        }
+      }
+    };
+
+    $scope.ecdapp.reconfigDeploymentById = function(newInputs) { 
+      $scope.ecdapp.updatingDeployment = true;
+      angular.copy($scope.ecdapp.app_config_from_bp, $scope.ecdapp.app_config_bakup);
+      for (let [input_key, input_val] of Object.entries(newInputs)) {
+        $scope.ecdapp.replaceNewInput(input_key, input_val, 
+            $scope.ecdapp.app_config_from_bp);
+      }
+      angular.copy($scope.ecdapp.app_config_from_bp, $scope.ecdapp.app_config_new);
+      angular.copy($scope.ecdapp.app_config_bakup, $scope.ecdapp.app_config_from_bp);
+      $scope.ecdapp.app_config_latest_str = 
+        JSON.stringify($scope.ecdapp.app_config_new, undefined, 4);
+
+      $scope.ecdapp.reconfigRequest.parameters.operation_kwargs.application_config = 
+        $scope.ecdapp.app_config_new;      
+
+      DeploymentService.reconfigFlow($scope.ecdapp.reconfigRequest).then(function(jsonObj) {       
+        if (debug)
+          $log.debug("appReconfigCtrl.reconfigFlow response: " + JSON.stringify(jsonObj));
+        if (jsonObj.error) {
+          $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error;
+          $scope.ecdapp.updatingDeployment = false;
+        }
+        else {
+          $scope.ecdapp.updatingDeployment = false;
+          alert('application reconfig request for ' + $scope.ecdapp.deploymentId + ' successfully went through to Cloudify. Reconfig is now pending');               
+          $modalInstance.dismiss('cancel');
+        }
+      }, function(error) {
+        $scope.ecdapp.updatingDeployment = false;
+        alert('Failed to perform reconfig for Deployment Id ' + $scope.ecdapp.deploymentId);
+        $log.error('appReconfigCtrl.reconfigFlow failed: ' + error);
+      });
+
+    };            
+  });
+  
+       /*************************************************************************/
+       appDS2.controller('deploymentUpgradeCtrl', function(
+           $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) {
+
+         'use strict';
+
+         // Controls logging in this controller
+         var debug = false;
+
+         // this object holds all app data and functions
+         $scope.ecdapp = {};
+         $scope.ecdapp.label = 'Deployment Upgrade';
+         $scope.ecdapp.deployment = null;
+         $scope.ecdapp.deploymentRef = message.deployment.id;   //THIS IS THE BLUEPRINT ID
+         $scope.ecdapp.bpId = message.deployment.blueprint_id;
+         $scope.ecdapp.serviceId = message.deployment.serviceId;
+         $scope.ecdapp.errMsg = null;
+         $scope.ecdapp.isDataLoading = true;
+         $scope.ecdapp.isRequestFailed = false;
+         $scope.ecdapp.updatingDeployment = false;
+         var selTenant = message.deployment.tenant_name;
+         if ( typeof selTenant === "undefined" ) {
+           selTenant = "default_tenant";
+         }
+         $scope.ecdapp.tenant = selTenant;
+         $scope.ecdapp.ui_tenant = selTenant;
+         $scope.ecdapp.parmFileDict = {};
+
+         // This object holds data for editing the input parameters
+         $scope.ecdapp.editRequest = {
+             deployment_id: '',
+             type_id: '',
+             fileModel: null,
+             resourceConstants: {},
+             resourceDefinitionChanges: {}
+         };
+         //First get the blueprintId associated with the deployment, along with the inputs of the deployment
+         InventoryDeploymentService.getDeployment($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) {
+           if (deployment.items.length == 0) {
+             $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!";
+             $log.error("InventoryDeploymentSerice.getDeployment failed: "
+                 + $scope.ecdapp.errMsg);
+             $scope.ecdapp.isRequestFailed = true;
+           } 
+           // Deployment IDs are unique, so this will always return exactly one item!
+           else {
+             $scope.ecdapp.errMsg = null;
+             $scope.ecdapp.deployment = deployment.items[0];
+             $scope.ecdapp.isRequestFailed = false;
+             $scope.ecdapp.editRequest.type_id = deployment.items[0].blueprint_id;
+             $scope.ecdapp.parmFileDict = deployment.items[0].inputs;
+             Object.keys($scope.ecdapp.parmFileDict).map(function(key, index) {
+               if (key == 'config-format' || key == 'config-url' || key == 'chart-version' || key == 'chart-repo-url' || key == 'config-set') {
+                 $scope.ecdapp.editRequest.resourceDefinitionChanges[key] = $scope.ecdapp.parmFileDict[key];
+               } else {
+                 $scope.ecdapp.editRequest.resourceConstants[key] = $scope.ecdapp.parmFileDict[key];
+               }
+               //$scope.ecdapp.editRequest.resourceDefinitionChanges['config_set'] = '';
+             });
+           }
+           $scope.ecdapp.isDataLoading = false;
+         },
+         function(error) {
+           $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error));
+           $scope.ecdapp.isRequestFailed = true;
+           $scope.ecdapp.errMsg = error;
+           $scope.ecdapp.isDataLoading = false;
+         });
+
+         /**
+          * Validates content of user-editable fields.
+          * Returns null if all is well, 
+          * a descriptive error message otherwise.
+          */
+
+         $scope.ecdapp.validateRequest = function(editRequest) {
+           if (editRequest == null)
+             return 'No data found.\nPlease enter some values.';
+           if (editRequest["chart-version"] == null || editRequest["chart-version"].trim() == '')
+             return 'Chart version is required.\nPlease enter a value.';
+           if (!editRequest["config-format"] || editRequest["config-format"].trim() == '') {
+             return 'config format is required.\nPlease enter a value.';
+           }
+           if ((!editRequest["config-url"] || editRequest["config-url"].trim() == '') && 
+               (!editRequest["config_set"] || editRequest["config_set"].trim() == '')) {
+             return 'Config URL or Config set is required.\nPlease enter either of these input values';
+           }
+           return null;
+         };
+
+         /**
+          * Helm upgrade for deployment based on parameters user enters in modal popup
+          * First retrieves the node-id using the blueprintId
+          * Using the node-id and deploymentId, retrieves the node-instance-id
+          * Calls the start execution API, passing object with deploymentId, and changed parameters
+          */
+
+         $scope.ecdapp.upgradeWorkflow = function(resourceDefinitionChanges) {
+           $scope.ecdapp.updatingDeployment = true;
+           let nodeId = '';
+
+           // validate request
+           var validateMsg = $scope.ecdapp.validateRequest(resourceDefinitionChanges);
+           if (validateMsg != null) {
+             alert('Invalid Request:\n' + validateMsg);
+             $scope.ecdapp.updatingDeployment = false;
+             return;     
+           }
+           //get node id from blueprint
+           InventoryDeploymentService.getBlueprint($scope.ecdapp.bpId, $scope.ecdapp.tenant).then(function(blueprint) {
+             if (debug)
+               $log.debug("inventoryDeploymentUpgradeCtrl.getBlueprint response: " + JSON.stringify(blueprint));
+             if  (blueprint.error) {
+               $scope.ecdapp.errMsg = 'Request Failed: ' + blueprint.error;
+               $scope.ecdapp.updatingDeployment = false;
+             }
+             else {
+               //console.log('returned blueprint:' + blueprint);
+               let count = 0;
+               //console.log("number of node objects in array: " + blueprint.items[0].plan.nodes.length);
+               //console.log(JSON.stringify(blueprint));
+               blueprint.items[0].plan.nodes.map(function(node) {
+                 if (node.type == 'onap.nodes.component') {
+                   //want to get FIRST node with type 'cloudify.kubernetes.resources.Deployment' so only set nodeID for first matching type
+                   if (count < 1) {
+                     nodeId = node.id;
+                   }
+                   count = count + 1;
+                 }
+               });
+               //if no node has type 'cloudify.kubernetes.resources.Deployment', return message saying no deployment exists and exit (ie nodeId still is '')
+               if (nodeId == '') {
+                 alert('Failed to retrieve Node Id. No matching deployment found (no deployment exists)');
+                 $scope.ecdapp.updatingDeployment = false;
+                 return;
+               }
+               //found node id. now need to retrieve node-instance-id
+               console.log('%c RETRIEVED NODE ID: ' + nodeId, 'color: orange; font-weight: bold;');
+               let nodeInstanceId = '';
+               InventoryDeploymentService.getNodeInstanceId($scope.ecdapp.deploymentRef, nodeId, $scope.ecdapp.tenant).then(function(jsonObj) {
+                 if (debug)
+                   $log.debug("inventoryDeploymentUpgradeCtrl.getNodeInstanceId response: " + JSON.stringify(jsonObj));
+                 if (jsonObj.error) {
+                   $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error;
+                   $scope.ecdapp.updatingDeployment = false;
+                 }
+                 else {
+                   //if nodeInstanceId is still '' then it wasn't found, stop flow)
+                   if (jsonObj.items[0].id == '') {
+                     alert('Failed to retrieve Node Instance Id for Node Id' + nodeId);
+                     $scope.ecdapp.updatingDeployment = false;
+                     return;
+                   }
+                   //found node-instance-id. now need to update resources
+                   nodeInstanceId = jsonObj.items[0].id;
+                   console.log('%c RETRIEVED NODE INSTANCE ID:' + nodeInstanceId, 'color: green; font-weight: bold;');
+                   //console.log(resourceDefinitionChanges);
+                   InventoryDeploymentService.upgradeFlow($scope.ecdapp.deploymentRef, nodeInstanceId, resourceDefinitionChanges, $scope.ecdapp.tenant).then(function(jsonObj) {
+                     if (debug)
+                       $log.debug("inventoryDeploymentUpgradeCtrl.updateResources response: " + JSON.stringify(jsonObj));
+                     if (jsonObj.error) {
+                       $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error;
+                       $scope.ecdapp.updatingDeployment = false;
+                     }
+                     else {
+                       console.log('%c UPDATE RESOURCES COMPLETED', 'color: magenta; font-weight: bold;');
+                       //console.log(jsonObj);
+                       $scope.ecdapp.updatingDeployment = false;
+                       alert('Helm Upgrade request for ' + $scope.ecdapp.deploymentRef + ' successfully went through to Cloudiy. Upgrade is now pending');               $modalInstance.dismiss('cancel');
+                     }
+                   }, function(error) {
+                     $scope.ecdapp.updatingDeployment = false;
+                     alert('Failed to perform upgrade for Deployment Id ' + $scope.ecdapp.deploymentRef + ' and Node Instance Id ' + nodeInstanceId + '. Please retry.');
+                     $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error);
+                   });
+                 }
+               }, function(error) {
+                 $scope.ecdapp.updatingDeployment = false;
+                 alert('Failed to get Node Instance Id for deploymentId ' + $scope.ecdapp.deploymentRef + ' and Node Id ' + nodeId + '. Please retry.');
+                 $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error);
+               });
+
+             }
+           }, function(error) {
+             $scope.ecdapp.updatingDeployment = false;
+             alert('Failed to get blueprint for blueprintId ' + $scope.ecdapp.deploymentRef + '. Please retry.');
+             $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error);
+           });
+         };
+
+         /**
+          * Handler for file-read event reads file, parses JSON, validates content.
+          */
+
+         var fileReader = new FileReader();
+         fileReader.onload = function(event) {
+           let jsonString = fileReader.result;
+           if (debug)
+             $log.debug('fileReader.onload: read: ' + jsonString);
+           let ydict = {};
+           try {
+             ydict = JSON.parse(jsonString);
+           }
+           catch (ex) {
+             alert('Failed to parse file as JSON:\n' + ex);
+           }
+           // Process the file
+           for (var ykey in ydict) {
+             let yval = ydict[ykey];
+             if (debug)
+               $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey);
+             // Allow only expected keys with scalar values
+             if (! (ykey in $scope.ecdapp.parmFileDict))
+               alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey);
+             if (yval.constructor === {}.constructor)
+               $scope.ecdapp.parmFileDict[ykey] = angular.toJson(yval);
+             else
+               $scope.ecdapp.parmFileDict[ykey] = yval;
+           }
+           if (debug)
+             $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.parmFileDict));
+
+           // Update table in all cases 
+           //$scope.ecdapp.setResourceDefinitionChanges($scope.ecdapp.editRequest.resourceDefinitionChanges, $scope.ecdapp.editRequest.parmFileDict);
+           Object.keys($scope.ecdapp.parmFileDict).map(function(key, index) {
+             
+             if (key == 'config-format' || key == 'config-url' || key == 'chart-version' || key == 'chart-repo-url' || key == 'config-set') {
+          $scope.ecdapp.editRequest.resourceDefinitionChanges[key] = $scope.ecdapp.parmFileDict[key];
+        } else {
+          $scope.ecdapp.editRequest.resourceConstants[key] = $scope.ecdapp.parmFileDict[key];
+        }
+           });
+           //$scope.$apply();
+         };
+
+         // Handler for file-select event
+         $scope.handleFileSelect = function() {
+           if (debug)
+             $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name);
+           fileReader.readAsText($scope.ecdapp.editRequest.fileModel);
+         };
+
+       });
+
index cee83c3..f7f9db3 100644 (file)
@@ -1,24 +1,3 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
 appDS2.factory('DeploymentService', function ($http, $q, $log) {
        return {
                /**
@@ -27,10 +6,19 @@ appDS2.factory('DeploymentService', function ($http, $q, $log) {
                 * @param {Number} viewPerPage - number of items per page; e.g., 25
                 * @return {JSON} Response object from remote side
                 */
-               getDeployments: function(pageNum,viewPerPage) {
+               getDeployments: function(pageNum,viewPerPage,sortBy,searchBy) {
                        // cache control for IE
                        let cc = "&cc=" + new Date().getTime().toString();
-                       let url = 'deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc;
+           let url = null;
+           if (sortBy && searchBy) {
+               url = 'deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&sortBy=' + sortBy + '&searchBy=' + searchBy + cc;
+           } else if (sortBy) {
+               url = 'deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&sortBy=' + sortBy + cc;
+           } else if (searchBy) {
+                           url = 'deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&searchBy=' + searchBy + cc;
+                       } else {
+                           url = 'deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage +cc;
+                       }
                        return $http({
                                        method: 'GET',
                                        url: url,
@@ -84,6 +72,69 @@ appDS2.factory('DeploymentService', function ($http, $q, $log) {
                                $log.error('DeploymentService.deleteDeployment failed: ' + JSON.stringify(error));
                                return $q.reject(error.statusText);
                        });
+               },
+               
+               getBlueprintContent: function(id, tenant) {
+                 let url ='blueprints/' + id + '/archive?tenant=' + tenant;
+      return $http({
+        method: 'GET',
+        url: url,
+        cache: false,
+        responseType: 'yaml' 
+    }).then(function(response) {
+      // This is called on response code 200..299.
+      // On success, response.data is null.
+      // On failure, response.data has an error message.
+/*      var contentType = "application/octet-stream";
+      var data = response.data
+      var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
+      if (urlCreator) {
+          var blob = new Blob([data], { type: contentType });
+          var url = urlCreator.createObjectURL(blob);
+          var a = document.createElement("a");
+          document.body.appendChild(a);
+          a.style = "display: none";
+          a.href = url;
+          a.download = "blueprint.yaml"; //you may assign this value from header as well 
+          a.click();
+          window.URL.revokeObjectURL(url);
+      }*/
+      return response;
+    }, 
+    function(error) {
+      $log.error('DeploymentService.getBlueprintContent failed: ' + JSON.stringify(error));
+      return $q.reject(error.statusText);
+    });
+               },
+               
+               reconfigFlow: function(reconfigRequest) {
+                 let body = {
+                     "deployment_id": reconfigRequest.deployment_id,
+                     "workflow_id": reconfigRequest.workflow_id,
+                     "allow_custom_parameters": true,
+                     "force": true,
+                     "tenant": reconfigRequest.tenant,
+                     "parameters": reconfigRequest.parameters
+                 };
+                 let urlStr = 'executions';
+                 return $http({
+                   method: 'POST',
+                   url: urlStr,
+                   data: body,
+                   cache: false,
+                   responseType: 'json'
+                 }).then(function(response) {
+                   if (response.data == null) 
+                     return $q.reject('DeploymentService.reconfigFlow: response.data null or not object');
+                   else {
+                     console.log(response);
+                     return response.data;
+                   }
+                 },
+                 function(error) {
+                   $log.error('DeploymentService.reconfigFlow failed: ' + JSON.stringify(error));
+                   return $q.reject(error.statusText);
+                 });
                }
        };
 });
index f4a4cdd..d051495 100644 (file)
@@ -1,3 +1,43 @@
+<script type="text/ng-template" id="blueprint_content_popup.html">
+  <div class="b2b-modal-header ng-scope">
+    <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
+    <div class="corner-button in">
+      <button type="button" class="close" aria-label="Close"
+        ng-click="$dismiss('cancel')"></button>
+    </div>
+  </div>
+  <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+    role="region" aria-label="Modal body content">
+    <!-- show progress indicator -->
+    <div ng-show="ecdapp.isDataLoading">
+      <div class="span" style="margin-bottom: 20px;">
+        <i class="icon-spinner small" role="img"
+          aria-label="Please wait while the content loads"></i> Please
+        wait while the content loads.
+      </div>
+    </div>
+    <div ng-show="ecdapp.errMsg">
+      <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
+    </div>
+    <div class="row-nowrap">
+      <div class="span12">
+        <label for="typeName">Blueprint Name</label>
+        <!--not editable-->
+        <input id="typeName" class="span12" type="text"
+          disabled="disabled" data-ng-model="ecdapp.typeName" />
+      </div>
+    </div>
+    <div ng-hide="ecdapp.errMsg">
+      <pre>{{ecdapp.blueprint}}</pre>
+    </div>
+  </div>
+  <div class="b2b-modal-footer ng-scope ng-isolate-scope">
+    <div class="cta-button-group in">
+      <button class="btn btn-alt btn-small" type="button"
+        ng-click="$dismiss('cancel');">Close</button>
+    </div>
+  </div>
+</script>
 <script type="text/ng-template" id="deployment_execute_popup.html">
 
        <style>
                                <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict">
                                                        <tr id="tr-rowData">
                                                                <td ng-bind="pkey"/>
-                                                               <td ng-bind="pval"/>
+                                                               <td><input id="parameterValue" class="span12" type="text" data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" autofocus/></td>
                                                        </tr>
                                                </tbody>
                                        </table>
 
 </script>
 
-<script type="text/ng-template" id="deployment_delete_popup.html">
-       
-
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+<script type="text/ng-template" id="app_reconfig_view_popup.html">
+  <div class="b2b-modal-header ng-scope">
+  <h2 id="myModalLabel" modal-title="">
+    <span style="font-weight: bolder; background: aqua;">{{ecdapp.deploymentId}}</span>
+    Execute Reconfiguration
+  </h2>
+  <div class="corner-button in">
+    <button type="button" class="close" aria-label="Close"
+      ng-click="$dismiss('cancel')"></button>
+  </div>
+  </div>
+  <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
                role="region" aria-label="Modal body content">
-               <div class="span12">
-                       <div class="form-row">                                  
-                               <div class="field-group">
-                                       <label>
-                                               Delete deployment with ID '{{ecdapp.deploymentId}}'?
-                                       </label>
+     <!-- show progress indicator -->
+    <div ng-show="ecdapp.isDataLoading">
+      <div class="span" style="margin-bottom: 20px;">
+        <i class="icon-spinner small" role="img"
+          aria-label="Please wait while the content loads"></i> Please
+        wait while the content loads.
+      </div>
+    </div>
+    <div ng-show="ecdapp.errMsg">
+      <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
+    </div>
+       <div ng-hide="ecdapp.isDataLoading" style="margin-top: 10px;">
+        <div class="row-nowrap">
+                       <div class="span9">
+                               <div class="form-row">
+                                       <label for="parameters">Configuration Inputs</label>
+                                       <div class="tooltip" b2b-tooltip trigger="focus" style="float:right;">
+                                               <a  href="javascript:void(0)" class="tooltip-element" data-placement="left" role="button" aria-label="Help"  aria-describedby="tooltiptext1" >
+                                               blueprint
+                                               <div class="arrow"></div>
+                                               </a>
+                                               <div class="tooltip-wrapper" role="tooltip" aria-live="polite" aria-atomic="false" style="z-index:1111">
+                                                       <div class="tooltip-size-control">
+                                                               <div class="helpertext" tabindex="-1" role="tooltip" id="tooltiptext1">  
+                                                                       <div class="popover-title">Application Configuration Blueprint</div>  
+                                                                       <div class="popover-content">
+                                                                               <pre>{{ecdapp.app_config_bp_str}}</pre>
+                                                                       </div>
+                                                               </div>
+                                                       </div>
+                                               </div>
+                                       </div>
+                                       <div b2b-file-drop
+                                               file-model="ecdapp.editRequest.fileModel"
+                                               on-drop="handleFileSelect()" align="center">
+                                               <span b2b-file-link
+                                               file-model="ecdapp.editRequest.fileModel"
+                                               on-file-select="handleFileSelect()"> Drag
+                                               &amp; drop a parameters JSON file here, or click to
+                                               browse. </span>
+                                       </div>
+                               </div>
+                               <div class="ecd-parameter-table">
+                                       <table id="parameters">
+                                               <tr id="ecd-table-header">
+                                               <th width="20%">Name</th>
+                                               <th width="40%">Initial Value</th>
+                                               <th width="40%">Current Value</th>
+                                               </tr>
+                                               <tbody
+                                               ng-repeat="(pkey, pval) in ecdapp.parmFileDict">
+                                               <tr id="tr-rowData">
+                                                       <td>
+                                                       <div style="font-weight: bold;">{{pkey}}</div> 
+                                                       <div style="margin-top: 8px; font-weight: lighter;">{{ecdapp.descriptionDict[pkey]}}</div>
+                                                       </td>
+                                                       <td><input class="span12"
+                                                       type="text" disabled="disabled"
+                                                       data-ng-model="ecdapp.parmFileDict[pkey]"
+                                                       autofocus />
+                                                       </td>
+                                                       <td><input class="span12"
+                                                       type="text"
+                                                       data-ng-model="ecdapp.parmCurrFileDict[pkey]"
+                                                       ng-keyup="ecdapp.refreshAppConfig(ecdapp.parmCurrFileDict);"
+                                                       autofocus />
+                                                       </td>
+                                               </tr>
+                                               </tbody>
+                                       </table>
                                </div>
+                               <!--
+                               <div class="reconfig-params" style="margin-top: 10px;">
+                                       <label for="parameters">Configuration Override</label>
+                                       <table id="reconfig">
+                                               <tr id="ecd-table-header">
+                                               <th width="50%">Name</th>
+                                               <th width="50%">Value</th>
+                                               </tr>
+                                               <tbody
+                                               ng-repeat="(pkey, pval) in ecdapp.appConfigOverride">
+                                               <tr id="tr-rowData">
+                                                       <td>
+                                                       <div style="font-weight: bold;">{{pkey}}</div>
+                                                       </td>
+                                                       <td><input class="span12"
+                                                       type="text"
+                                                       ng-keyup="ecdapp.refreshAppConfigOverride(pkey, pval);"
+                                                       data-ng-model="ecdapp.appConfigOverride[pkey]" autofocus />
+                                                       </td>
+                                               </tr>
+                                               </tbody>
+                                       </table>
+                               </div>
+                               -->
                        </div>
-               </div>
-
-               <div class="span12">
-                       <div class="form-row">
-                               <label for="ignoreLiveNodesCheck">&nbsp;</label>
-                               <div class="field-group">
-                       <label for="ignoreLiveNodes" class="checkbox">
-                               <input id="ignoreLiveNodes" type="checkbox" ng-model="ecdapp.ignoreLiveNodes" />
-                                               <i class="skin"></i><span>Ignore Live Nodes</span>
-                       </label>
+                       <div class="span3">
+                               <div class="form-row">
+                               <label style="text-decoration: underline;">Application Configuration</label>
+                               <pre style="font-weight: bold;">{{ecdapp.app_config_latest_str}}</pre>
                                </div>
                        </div>
-               </div> 
-
+        </div>
        </div>
-
-       <div class="b2b-modal-footer ng-scope ng-isolate-scope">
+    <!-- show progress indicator -->
+    <div style="width: 100%;">
+      <div ng-show="ecdapp.updatingDeployment"
+        style="display: table; margin: 0 auto;" class="span">
+        <i class="icon-spinner small" role="img"
+          aria-label="Update Deployment in Progress..."></i> Update
+        Deployment in Progress...
+      </div>
+    </div>
+       <div ng-hide="ecdapp.isDataLoading" class="b2b-modal-footer ng-scope ng-isolate-scope">
                <div class="cta-button-group in">
                        <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="ecdapp.deleteDeploymentById(deployment);">
-                               Delete
+                                       ng-show="!ecdapp.updatingDeployment" 
+                                       ng-click="ecdapp.reconfigDeploymentById(ecdapp.parmCurrFileDict);">                                     
+                               Submit
                        </button>
                        <button class="btn btn-small" type="button"
                                ng-click="$dismiss('cancel')">
index c414484..211d17d 100644 (file)
 <div id="page-content">
+  <h1 class="heading-page" id="deployments-page">Deployments</h1>
+  <div style="float: right; margin-top: -20px;" class="span4 form-row">
+    <div ng-show="ecdapp.groupByTenant" class="field-group span10"> 
+      <label title="Cloudify Tenant" for="cldTenants">Tenant: {{ecdapp.selectedTenant}}</label> 
+      <select id="cldTenants" name="cldTenants" b2b-dropdown placeholder-text="Select Tenant" 
+        class="span8"
+        ng-model="ecdapp.selectedTenant"
+        ng-change="ecdapp.tenantChangeHandler()">
+        <option b2b-dropdown-list
+          option-repeat="d in ecdapp.availableTenants" value="{{d}}">{{d}}</option>
+      </select>
+    </div>
+  </div>
+  <!-- show progress indicator -->
+  <div ng-show="ecdapp.isDataLoading">
+    <div class="span" style="margin-bottom: 20px;">
+      <i class="icon-spinner small" role="img"
+        aria-label="Please wait while the content loads"></i> Please
+      wait while the content loads.
+    </div>
+  </div>
+  <div>
+    <div id="button-search-row" style="margin-left: 45px; width: 60%;"
+      ng-hide="ecdapp.isDataLoading">
+      <div>
+        <div class="group">
+          <div class="advanced-search">
+            <button tabindex="-1"
+              style="position: absolute; margin-left: -35px; border: none; background: none; top: 5px;"
+              "class="btn btn-small" title="Reload view without applying basic filters"
+              type="button" ng-click="ecdapp.reloadTable()">
+              <i class="icon-arrows-replay-restart"></i>
+            </button>
+            <button tabindex="1"
+              style="position: absolute; border: none; background: none; margin-left: 5px; top: 5px;"
+              "class="btn btn-medium" type="button"
+              ng-click="ecdapp.filterBySvc()">
+              <i class="ion-search"></i>
+            </button>
+            <input tabindex="0" style="padding-left: 50px;"
+              class="advanced-search-input" type="text"
+              placeholder="Search Deployments"
+              title="multiple deployment name patterns - comma separated values"
+              ng-model="ecdapp.searchString"
+              ng-keydown="[13, 32].includes($event.keyCode) && ecdapp.filterBySvc()"></input>
+            <button type="button" id="show-menu-filters"
+              class="btn dropdown-toggle"
+              ng-click="ecdapp.toggleMoreFilters()" data-toggle="dropdown"
+              title="More Filters">
+              <i class="icon-controls-down"></i>
+            </button>
+          </div>
+        </div>
+        <div class="menu-filters" ng-show="ecdapp.showingMoreFilters">
+          <div class="group">
+            <label class="col-sm-3 control-label">Service IDs: </label>
+            <ui-select multiple ng-model="ecdapp.selectedServices"
+              ng-disabled="ecdapp.usingAafFilter || ecdapp.usingDcaeTargetTypeFilter"
+              theme="bootstrap" close-on-select="false" title="Service ID">
+            <ui-select-match class="ui-select-match">{{$item}}</ui-select-match>
+            <ui-select-choices class="ui-select-choices"
+              repeat="service in ecdapp.availableServices | filter:$select.search"
+              position='down'> {{service}} </ui-select-choices> </ui-select>
+          </div>
+          <div class="group" ng-hide="ecdapp.filterByUser">
+            <label class="col-sm-3 control-label">Owners: </label>
+            <ui-select multiple ng-model="ecdapp.selectedOwner"
+              theme="bootstrap" close-on-select="false"
+              title="Blueprint owner"> <ui-select-match
+              class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices
+              class="ui-select-choices"
+              repeat="owner in ecdapp.bpOwners | filter:$select.search"
+              position='down'> {{owner}} </ui-select-choices> </ui-select>
+          </div>
+          <div class="group">
+            <label class="col-sm-3 control-label">Status: </label>
+            <ui-select multiple ng-model="ecdapp.selectedStatus"
+              ng-disabled="ecdapp.usingAafFilter || ecdapp.usingDcaeTargetTypeFilter"
+              theme="bootstrap" close-on-select="false"
+              title="Install Status"> <ui-select-match
+              class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices
+              class="ui-select-choices"
+              repeat="status in ecdapp.availableStatus | filter:$select.search"
+              position='down'> {{status}} </ui-select-choices> </ui-select>
+          </div>
+          <div title="Helm only" style="margin-top: 10px;">
+            <label for="checkbox1" class="checkbox"> <input
+              ng-disabled="ecdapp.usingAafFilter || ecdapp.usingDcaeTargetTypeFilter"
+              id="checkbox1" type="checkbox" ng-model="ecdapp.isHelmType"><i
+              class="skin"></i><span>Helm Chart Deployment</span>
+            </label>
+          </div>
+          <div class="group">
+            <label class="col-sm-3 control-label">AAF Username: </label> <input
+              tabindex="0" class="advanced-search-input" type="text"
+              title="Filter by AAF Username in inputs - *Disables other fields*"
+              ng-disabled="ecdapp.usingDcaeTargetTypeFilter"
+              ng-model="ecdapp.aafUsernameString"
+              ng-change="ecdapp.handleDisableOtherFields()"></input>
+          </div>
+          <div class="group">
+            <label class="col-sm-3 control-label">DCAE Target
+              Type: </label> <input tabindex="0" class="advanced-search-input"
+              type="text"
+              title="Filter by DCAE Target Type in inputs - *Disables other fields*"
+              ng-disabled="ecdapp.usingAafFilter"
+              ng-model="ecdapp.dcaeTargetTypeString"
+              ng-change="ecdapp.handleDisableOtherFields()"></input>
+          </div>
+          <div class="group" style="float: right;">
+            <button tabindex="-1" class="btn btn-small"
+              title="Reset Filters" type="button"
+              ng-click="ecdapp.resetFilters()">
+              <i class="icon-arrows-replay-restart"></i>
+            </button>
+            <button tabindex="1" class="btn btn-small"
+              title="Filtered search" type="button"
+              ng-click="ecdapp.extendedfilterSrch()">
+              <i class="ion-search"></i>
+            </button>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div id="depFilter" style="margin-left: 20px;margin-top: 10px; margin-bottom: 10px;" title="Additional filters">
+      <label for="checkbox3" class="checkbox" style="margin-right: 100px;"> 
+      <input id="checkbox3" type="checkbox" ng-model="ecdapp.filterByUser" ng-change="ecdapp.toggleUserFilt()" class="ng-valid ng-dirty ng-valid-parse ng-touched">
+      <i class="skin"></i><span>My Deployments</span>
+      </label> 
+      <label for="checkbox1" class="checkbox" style="margin-right: 20px;"> 
+      <input id="checkbox1" type="checkbox" ng-model="ecdapp.useCache" ng-change="ecdapp.toggleRefresh()" class="ng-pristine ng-untouched ng-valid">
+      <i class="skin"></i><span>Cache</span>
+      </label>
+      <label for="checkbox2" class="checkbox" > 
+      <input id="checkbox2" type="checkbox" ng-model="ecdapp.groupByTenant" ng-change="ecdapp.toggleTenantFilt()" class="ng-valid ng-dirty ng-valid-parse ng-touched">
+      <i class="skin"></i><span>Tenant</span>
+      </label>
+    </div>
+  </div>
 
-       <h1 class="heading-page" id="deployments-page">Deployments</h1>
-       
-       <!-- show progress indicator -->
-       <div ng-show="ecdapp.isDataLoading">
-               <div class="span" style="margin-bottom:20px;">
-               <i class="icon-primary-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-               Please wait while the content loads.
-           </div>
-       </div>
+  <div ng-show="ecdapp.isRequestFailed">
+    <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
+  </div>
+  <div ng-hide="ecdapp.isRequestFailed">
+    <div b2b-table id="deployments-table" class="b2b-table-div"
+      table-data="ecdapp.tableData"
+      current-page="ecdapp.currentPageIgnored"
+      next-sort="ecdapp.nextSortIgnored">
+      <table>
+        <thead b2b-table-row type="header">
+          <tr id="th-header-row">
+            <th b2b-table-header sortable="false" key="id" 
+              ng-click="ecdapp.sortTable('id')">ID</th>
+            <th b2b-table-header sortable="false" key="blueprint_id"
+              ng-click="ecdapp.sortTable('blueprint_id')">Blueprint ID</th>
+            <!-- <th b2b-table-header key="description">Description</th> -->
+            <th b2b-table-header sortable="false" key="created_at"
+              ng-click="ecdapp.sortTable('created_at')">Created Date</th>
+            <th b2b-table-header sortable="false" key="owner"
+              ng-click="ecdapp.sortTable('created_at')">Owner</th>
+            <th b2b-table-header sortable="false" key="tenant" >Tenant</th>
+            <!-- <th b2b-table-header key="updated_at">Updated Date</th>-->
+            <th b2b-table-header sortable="false" key="status">Health</th>
+            <th b2b-table-header sortable="false">Actions</th>
+            <!-- <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th> -->
+          </tr>
+        </thead>
+        <tbody b2b-table-row type="body"
+          row-repeat="rowData in ecdapp.tableData">
+          <tr id="tr-rowData">
+            <td b2b-table-body>
+              <div>
+                <div ng-if="rowData.lastExecution.status !== undefined" class="stat_tooltip"
+                  style="width: 30px; position: relative;">
+                  <img ng-if="rowData.lastExecution.status !== undefined &&
+                    rowData.lastExecution.status == 'terminated'"
+                    src="static/fusion/images/active.png"/> 
+                  <img ng-if="rowData.lastExecution.status !== undefined &&
+                    rowData.lastExecution.status == 'failed'"
+                    src="static/fusion/images/inactive.png"/>
+                  <img ng-if="rowData.lastExecution.status !== undefined &&
+                    rowData.lastExecution.status == 'started'"
+                    src="static/fusion/images/loading.gif"/>
+                  <img ng-if="rowData.lastExecution.status !== undefined &&
+                    rowData.lastExecution.status == 'pending'"
+                    src="static/fusion/images/loading.gif"/>
+                  <div class="wrapper">
+                    <div>
+                      <span
+                        style="left: 10px; font-weight: bold; position: relative; top: 10px;">Last
+                        Execution in Cloudify</span>
+                      <table>
+                        <thead>
+                          <tr>
+                            <th>Workflow</th>
+                            <th>Status</th>
+                            <th>Created</th>
+                            <th>Ended</th>
+                          </tr>
+                        </thead>
+                        <tbody>
+                          <tr>
+                            <td>{{rowData.lastExecution.workflow_id}}</td>
+                            <td>{{rowData.lastExecution.status}}</td>
+                            <td>{{rowData.lastExecution.created_at}}</td>
+                            <td>{{rowData.lastExecution.ended_at}}</td>
+                          </tr>
+                          <div
+                            style="position: relative; top: 150px; width: 250px; margin: 0 auto;">
+                            <button style="border-radius: 5px;"
+                              ng-click="ecdapp.viewDeploymentExecutionsModalPopup(rowData)">
+                              View Executions</button>
+                          </div>
+                        </tbody>
+                      </table>
+                    </div>
+                  </div>
+                </div>
+                <div style="position: relative; left: 10px;">{{rowData.id}}</div>
+              </div>
+            </td>
+            <td b2b-table-body>
+              <div ng-if="rowData.description !== undefined" class="gen_tooltip">{{rowData.blueprint_id}}
+                <div>
+                  <span class="gen_tooltiptext_r">{{rowData.description}}</span>
+                </div>
+              </div>
+              <div ng-if="rowData.description === undefined">{{rowData.blueprint_id}}</div>
+            </td>
+            <td b2b-table-body ng-bind="rowData.created_at"/>
+            <!--  <td b2b-table-body ng-bind="rowData.updated_at" /> -->
+            <td b2b-table-body ng-bind="rowData.owner"/>
+            <td b2b-table-body ng-bind="rowData.tenant_name"/>
+            <td b2b-table-body>
+              <img ng-if="rowData.healthStatus == 'passing'"
+              src="static/fusion/images/active.png"
+              title="{{rowData.healthStatus}}" /> <img
+              ng-if="rowData.healthStatus == 'critical'"
+              src="static/fusion/images/inactive.png"
+              title="{{rowData.healthStatus}}" /> </span>
+            </td>
+            <td b2b-table-body>
+              <div class="btn-group btn-actions"
+                style="margin-bottom: 0; box-shadow: none;">
+                <button type="button" class="btn dropdown-toggle"
+                  data-toggle="dropdown" title="More Actions">
+                  <i class="icon-apps-marketplace"></i>
+                </button>
+                <ul class="dropdown-menu">
+                  <li>
+                    <div ng-show="rowData.lastExecution.status != ''"
+                      ng-click="ecdapp.getBlueprintDataModal(rowData);">
+                      <i class="icon-documents-book ecd-icon-action"></i><a
+                        href="">View blueprint</a>
+                    </div>
+                  </li>
+                  <li>
+                    <div ng-show="rowData.lastExecution.status != ''"
+                      ng-click="ecdapp.viewDeploymentInputsModalPopup(rowData);">
+                      <i class="icoDocuments-report ecd-icon-action"></i><a
+                        href="">View Inputs</a>
+                    </div>
+                  </li>
+                  <li>
+                    <div ng-show="rowData.lastExecution.status != ''"
+                      ng-click="ecdapp.viewDeploymentExecutionsModalPopup(rowData);">
+                      <i class="icon-overview ecd-icon-action"></i><a
+                        href="">View executions</a>
+                    </div>
+                  </li>
+                  <li>
+                    <div
+                      ng-show="rowData.canDeploy && rowData.lastExecution.status === 'terminated'"
+                      ng-click="ecdapp.updateDeploymentModalPopup(rowData);">
+                      <i class="icon-misc-pen ecd-icon-action"></i><a
+                        href="">Update deployment</a>
+                    </div>
+                  </li>
+                  <li>
+                    <div
+                      ng-show="rowData.canDeploy && rowData.lastExecution.status != ''"
+                      ng-click="ecdapp.deleteDeploymentModalPopup(rowData);">
+                      <i class="icon-misc-trash ecd-icon-action"></i><a
+                        href="">Undeploy</a>
+                    </div>
+                  </li>
+                  <li>
+                    <div
+                      ng-show="rowData.isHelm && rowData.helmStatus"
+                      ng-click="ecdapp.checkHelmStatus(rowData);">
+                      <i class="icoDocuments-report ecd-icon-action"></i><a
+                        href="">Helm Status</a>
+                    </div>
+                  </li>
+                  <li>
+                    <div
+                      ng-show="rowData.canDeploy && rowData.isHelm"
+                      ng-click="ecdapp.upgradeDeploymentModalPopup(rowData);">
+                      <i
+                        class="icon-controls-down ecd-icon-action"></i><a
+                        href="">Helm Upgrade</a>
+                    </div>
+                  </li>
+                  <li>
+                    <div
+                      ng-show="rowData.canDeploy && rowData.isHelm"
+                      ng-click="ecdapp.rollbackDeploymentModalPopup(rowData);">
+                      <i
+                        class="icon-controls-up ecd-icon-action"></i><a
+                        href="">Helm Rollback</a>
+                    </div>
+                  </li>
+                  <li>
+                      <div                      
+                        ng-click="ecdapp.reconfigDeploymentModalPopup(rowData);">
+                        <i
+                          class="icon-datanetwork-contentdelivery ecd-icon-action"></i><a
+                          href="">Reconfigure</a>
+                      </div>
+                  </li>
+                </ul>
+              </div> <!-- .btn-group -->
+            </td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+    <div b2b-pagination="" total-pages="ecdapp.totalPages"
+      current-page="ecdapp.currentPageNum"
+      click-handler="pageChangeHandler" role="navigation"></div>
+  </div>
+</div>
+<div style="height: 10px;">
+  <!-- space between page number and black footer -->
+</div>
 
-       <div ng-hide="ecdapp.isDataLoading">
-               
-               <div id="button-search-row">
-                       <div style="float:right;">
-                          <div class="form-field form-field__small"> 
-                                       <input 
-                                               type="text"
-                                               placeholder="Search Deployments"
-                                               ng-model="ecdapp.searchString"/>
-                               </div>
-                       </div>
-               </div>
-
-               <div ng-show="ecdapp.isRequestFailed">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-       
-               <div ng-hide="ecdapp.isRequestFailed">
-       
-               <div 
-                       b2b-table 
-                       id="deployments-table"
-                       class="b2b-table-div" 
-                       table-data="ecdapp.tableData" 
-                       search-string="ecdapp.searchString" 
-                       current-page="ecdapp.currentPageIgnored"
-                       next-sort="ecdapp.nextSortIgnored">
-       
-                       <table>
-                       
-                           <thead b2b-table-row type="header"> 
-                                               <tr id="th-header-row">
-                                                       <th b2b-table-header key="deployment_id">ID</th>
-                                                       <th b2b-table-header key="blueprint_id">Blueprint ID</th>
-                                                       <th b2b-table-header key="description">Description</th>
-                                                       <th b2b-table-header key="created_at">Created Date</th>
-                                                       <th b2b-table-header key="updated_at">Updated Date</th>
-                                                       <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th>
-                                               </tr>
-                                       </thead>
-                                       
-                           <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData">
-                                               <tr id="tr-rowData">
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.id"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.blueprint_id"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.description"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.created_at"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.updated_at"/>                                          
-                                                       <td b2b-table-body> 
-                                                       <div ng-click="ecdapp.createExecutionModalPopup(rowData);">
-                                                               <a href="" title="Create execution" class="icon-controls-playalt ecd-icon-action"></a>
-                                                       </div>
-                                                       <div ng-click="ecdapp.deleteDeploymentModalPopup(rowData);">
-                                                               <a href="" title="Delete deployment" class="icon-misc-trash ecd-icon-action"></a>
-                                                       </div>
-                                               </td>
-                                               </tr>
-                                       </tbody>
-                               </table>
-                       </div> 
-               
-               <div b2b-pagination="" total-pages="ecdapp.totalPages" 
-                                               current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler"
-                                               role="navigation">
-               </div>
-                                       
-               </div>
-               </div>
-               
-               <div style="height: 10px;">
-                       <!-- space between page number and black footer -->
-               </div>
-               
-       </div><!-- loading -->
-       
-</div><!-- page content -->
+<!-- loading -->
+<!-- page content -->
index 34414c4..e4a8879 100644 (file)
@@ -1,24 +1,3 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
 appDS2.factory('ExecutionService', function ($http, $q, $log) {
        return {
                /**
@@ -88,8 +67,8 @@ appDS2.factory('ExecutionService', function ($http, $q, $log) {
                        });
                },
 
-               cancelExecution: function(id, deploymentId, action) {
-                       let url = 'executions/' + id + '?deployment_id=' + deploymentId + '&action=' + action;
+               cancelExecution: function(id, deploymentId, action, tenant) {
+                       let url = 'executions/' + id + '?deployment_id=' + deploymentId + '&action=' + action + '&tenant=' + tenant;
                        return $http({
                                        method: 'DELETE',
                                        url: url,
@@ -105,6 +84,6 @@ appDS2.factory('ExecutionService', function ($http, $q, $log) {
                                $log.error('ExecutionService.cancelExecution failed: ' + JSON.stringify(error));
                                return $q.reject(error.statusText);
                        });
-               }
+               },
        };
 });
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-service.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-service.js
new file mode 100644 (file)
index 0000000..0d34db3
--- /dev/null
@@ -0,0 +1,31 @@
+appDS2.factory('PluginService', function ($http, $q, $log) {
+       return {
+               /**
+                * Gets one page of objects.
+                * @param {Number} pageNum - page number; e.g., 1 
+                * @param {Number} viewPerPage - number of items per page; e.g., 25
+                * @return {JSON} Response object from remote side
+                */
+               getPlugins: function(pageNum,viewPerPage) {
+                       // cache control for IE
+                       let cc = "&cc=" + new Date().getTime().toString();
+                       let url = 'plugins?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc;
+                       return $http({
+                                       method: 'GET',
+                                       url: url,
+                                       cache: false,
+                                       responseType: 'json' 
+                       }).then(function(response) {
+                               if (response.data == null || typeof response.data != 'object') 
+                                       return $q.reject('PluginService.getPlugins: response.data null or not object');
+                               else 
+                                       return response.data;
+                       }, 
+                       function(error) {
+                               $log.error('PluginService.getPlugins failed: ' + JSON.stringify(error));
+                               return $q.reject(error.statusText);
+                       });
+               }
+               
+       };
+});
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-table-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/plugin-table-controller.js
new file mode 100644 (file)
index 0000000..23b59aa
--- /dev/null
@@ -0,0 +1,64 @@
+appDS2.controller('PluginsTableController', function(
+               $rootScope, $scope, $log, $modal, modalService, PluginService) {
+
+       'use strict';
+
+       // Controls logging in this controller
+       var debug = false;
+
+       // this object holds all app data and functions
+       $scope.ecdapp = {};
+       // models for controls on screen
+       $scope.ecdapp.tableData = [];
+       $scope.ecdapp.currentPageNum = 1;
+       $scope.ecdapp.viewPerPage = 10;
+       // other
+       $scope.ecdapp.errMsg = null;
+       $scope.ecdapp.isDataLoading = true;
+       $scope.ecdapp.isRequestFailed = false;
+
+       /**
+        * Loads the table. Interprets the remote controller's response and copies
+        * to scope variables. The response is either a list to be assigned to
+        * tableData, or an error to be shown.
+        */
+       $scope.ecdapp.loadTable = function() {
+               $scope.ecdapp.isDataLoading = true;
+               PluginService.getPlugins($scope.ecdapp.currentPageNum,
+                               $scope.ecdapp.viewPerPage).then(
+                               function(jsonObj) {
+                                       if (jsonObj.error) {
+                                               $log.error("PluginsTableController.loadTable failed: "
+                                                               + jsonObj.error);
+                                               $scope.ecdapp.isRequestFailed = true;
+                                               $scope.ecdapp.errMsg = jsonObj.error;
+                                               $scope.ecdapp.tableData = [];
+                                       } else {
+                                               $scope.ecdapp.isRequestFailed = false;
+                                               $scope.ecdapp.errMsg = null;
+                                               $scope.ecdapp.tableData = jsonObj;
+                                       }
+                                       $scope.ecdapp.isDataLoading = false;
+                               },
+                               function(error) {
+                                       $log.error("PluginsTableController.loadTable failed: "
+                                                       + error);
+                                       $scope.ecdapp.isRequestFailed = true;
+                                       $scope.ecdapp.errMsg = error;
+                                       $scope.ecdapp.tableData = [];
+                                       $scope.ecdapp.isDataLoading = false;
+                               });
+       };
+
+       /**
+        * Invoked at first page load AND when
+        * user clicks on the B2B pagination control. 
+        */
+       $scope.pageChangeHandler = function(page) {
+               if (debug)
+                       console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page);
+               $scope.ecdapp.currentPageNum = page;
+               $scope.ecdapp.loadTable();
+       }
+
+});
@@ -1,7 +1,5 @@
 <div id="page-content">
-
-       <h1 class="heading-page" id="controllers">ECOMP-C Instances</h1>
-       
+       <h1 class="heading-page" id="plugins-page">Cloudify Plugins</h1>
        <!-- show progress indicator -->
        <div ng-show="ecdapp.isDataLoading">
                <div class="span" style="margin-bottom:20px;">
            </div>
        </div>
 
-       <div ng-hide="ecdapp.isDataLoading">
-               
+       <div ng-hide="ecdapp.isDataLoading">    
                <div id="button-search-row">
                        <div style="float:right;">
                           <div class="form-field form-field__small"> 
                                        <input 
                                                type="text"
-                                               placeholder="Search Controllers"
+                                               placeholder="Search Plugins"
                                                ng-model="ecdapp.searchString"/>
                                </div>
                        </div>
                        <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
                </div>
        
-               <div ng-hide="ecdapp.isRequestFailed">
-       
+               <div ng-hide="ecdapp.isRequestFailed">  
                <div 
                        b2b-table 
-                       id="controllers-table"
+                       id="plugins-table"
                        class="b2b-table-div" 
                        table-data="ecdapp.tableData" 
                        search-string="ecdapp.searchString" 
                        current-page="ecdapp.currentPageIgnored"
                        next-sort="ecdapp.nextSortIgnored">
-       
-                       <table>
-                       
+                       <table>                 
                            <thead b2b-table-row type="header"> 
                                                <tr id="th-header-row">
-                                                       <th b2b-table-header sortable="false">Selected</th>
-                                                       <th b2b-table-header key="name">Name</th>
-                                                       <th b2b-table-header key="url">URL</th>
+                                                       <th b2b-table-header key="name">Package name</th>
+                                                       <th b2b-table-header key="version">Package version</th>
+                                                       <th b2b-table-header key="platform">Supported Platform</th>
+                                                       <th b2b-table-header key="distribution">Distribution</th>
+                                                       <th b2b-table-header key="uploaded_at">Uploaded at</th>
                                                </tr>
                                        </thead>
                                        
                            <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData">
                                                <tr id="tr-rowData">
-                                                       <td b2b-table-body>
-                                               <label class="radio">
-                                                       <input
-                                                               type="radio" 
-                                                                               name="ecdSelGroup" 
-                                                                               title="rowData.url"
-                                                                               ng-value="rowData.url" 
-                                                                               ng-model="ecdapp.radiobutton.url"
-                                                                               ng-change="ecdapp.selectController(rowData);">
-                                                               <i class="skin"></i>
-                                                               <span></span>
-                                               </label>
-                                                       </td>
                                                        <td b2b-table-body
-                                                               ng-bind="rowData.name"/>
+                                                               ng-bind="rowData.package_name"/>
                                                        <td b2b-table-body
-                                                               ng-bind="rowData.url"/>
+                                                               ng-bind="rowData.package_version"/>
+                                                       <td b2b-table-body
+                                                               ng-bind="rowData.supported_platform"/>
+                                                       <td b2b-table-body
+                                                               ng-bind="rowData.distribution"/>
+                                                       <td b2b-table-body
+                                                               ng-bind="rowData.uploaded_at"/>
                                                </tr>
                                        </tbody>
                                </table>
                        </div> 
                
-                       <!-- no pagination -->
-                       
+                       <div b2b-pagination="" total-pages="ecdapp.totalPages" 
+                                               current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler"
+                                               role="navigation">
+                       </div>
+                                       
                </div>
                
                <div style="height: 10px;">
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca-table-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca-table-controller.js
deleted file mode 100644 (file)
index cafc517..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-appDS2.controller('toscaTableController', function(
-               $rootScope, $scope, $log, $modal, modalService, ExecutionService) {
-
-       'use strict';
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       // models for controls on screen
-       $scope.ecdapp.tableData = [];
-       $scope.ecdapp.currentPageNum = 1;
-       $scope.ecdapp.viewPerPage = 10;
-       // other
-       $scope.ecdapp.errMsg = null;
-       $scope.ecdapp.isDataLoading = true;
-       $scope.ecdapp.isRequestFailed = false;
-
-       /**
-        * Loads the table. Interprets the remote controller's response and copies
-        * to scope variables. The response is either a list to be assigned to
-        * tableData, or an error to be shown.
-        */
-       $scope.ecdapp.loadTable = function() {
-               var toBeDefined = true;
-               if (toBeDefined) {
-                       $scope.ecdapp.isDataLoading = false;
-                       $scope.ecdapp.isRequestFailed = true;
-                       $scope.ecdapp.errMsg = 'TOSCA Models not available (yet).';
-               }
-               else {
-                       $scope.ecdapp.isDataLoading = true;
-                       ExecutionService.getExecutions($scope.ecdapp.currentPageNum,
-                                       $scope.ecdapp.viewPerPage).then(
-                                       function(jsonObj) {
-                                               if (jsonObj.error) {
-                                                       $log.error("executionController.loadTable failed: "
-                                                                       + jsonObj.error);
-                                                       $scope.ecdapp.isRequestFailed = true;
-                                                       $scope.ecdapp.errMsg = jsonObj.error;
-                                                       $scope.ecdapp.tableData = [];
-                                               } else {
-                                                       $scope.ecdapp.isRequestFailed = false;
-                                                       $scope.ecdapp.errMsg = null;
-                                                       $scope.ecdapp.totalPages = jsonObj.totalPages;
-                                                       $scope.ecdapp.tableData = jsonObj.items;
-                                               }
-                                               $scope.ecdapp.isDataLoading = false;
-                                       },
-                                       function(error) {
-                                               $log.error("executionController.loadTable failed: "
-                                                               + error);
-                                               $scope.ecdapp.isRequestFailed = true;
-                                               $scope.ecdapp.errMsg = error;
-                                               $scope.ecdapp.tableData = [];
-                                               $scope.ecdapp.isDataLoading = false;
-                                       });
-               }
-       };
-
-       /**
-        * Invoked at first page load AND when
-        * user clicks on the B2B pagination control. 
-        */
-       $scope.pageChangeHandler = function(page) {
-               // console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page);
-               $scope.ecdapp.currentPageNum = page;
-               $scope.ecdapp.loadTable();
-       }
-       
-       /**
-        * Shows a modal pop-up to confirm deletion. 
-        * On successful completion, updates the table.
-        */
-       $scope.ecdapp.deleteToscaModalPopup = function(execution) {
-               modalService.popupConfirmWin("Confirm", "Delete TOSCA model with ID '"
-                               + execution.id + "'?", function() {
-                       // TODO: gather action from user
-               })
-       };
-
-       // Populate the table on load. Note that the b2b selector code
-       // sets the page-number value, and the change event calls load table.
-       // Do not call this here to avoid double load:
-       // $scope.ecdapp.loadTable();
-
-});
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca_table.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/cloudify/tosca_table.html
deleted file mode 100644 (file)
index affec91..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-<div id="page-content">
-
-       <h1 class="heading-page" id="blueprints-page">TOSCA Models</h1>
-       
-       <!-- show progress indicator -->
-       <div ng-show="ecdapp.isDataLoading">
-               <div class="span" style="margin-bottom:20px;">
-               <i class="icon-primary-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-               Please wait while the content loads.
-           </div>
-       </div>
-
-       <div ng-hide="ecdapp.isDataLoading">
-               
-               <div id="button-search-row">
-                       <div style="float:right;">
-                          <div class="form-field form-field__small"> 
-                                       <input 
-                                               type="text"
-                                               placeholder="Search TOSCA Models"
-                                               ng-model="ecdapp.searchString"/>
-                               </div>
-                       </div>
-               </div>
-
-               <div ng-show="ecdapp.isRequestFailed">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-       
-               <div ng-hide="ecdapp.isRequestFailed">
-       
-               <div 
-                       b2b-table 
-                       id="tosca-table"
-                       class="b2b-table-div" 
-                       table-data="ecdapp.tableData" 
-                       search-string="ecdapp.searchString" 
-                       current-page="ecdapp.currentPageIgnored"
-                       next-sort="ecdapp.nextSortIgnored">
-       
-                       <table>
-                       
-                           <thead b2b-table-row type="header"> 
-                                               <tr id="th-header-row">
-                                                       <th b2b-table-header key="id">ID</th>
-                                                       <th b2b-table-header key="name">Name</th>
-                                                       <th b2b-table-header key="description">Description</th>
-                                                       <th b2b-table-header key="created_at">Created Date</th>
-                                                       <th b2b-table-header key="updated_at">Updated Date</th>
-                                                       <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th>
-                                               </tr>
-                                       </thead>
-                                       
-                           <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData">
-                                               <tr id="tr-rowData">
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.id"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.main_file_name"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.description"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.created_at"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.updated_at"/>                                          
-                                                       <td b2b-table-body> 
-                                                       <div ng-click="ecdapp.deleteToscaModalPopup(rowData);">
-                                                               <a href="" title="Delete TOSCA model" class="icon-misc-trash ecd-icon-action"></a>
-                                                       </div>
-                                               </td>
-                                               </tr>
-                                       </tbody>
-                               </table>
-                       </div> 
-               
-               <div b2b-pagination="" total-pages="ecdapp.totalPages" 
-                                               current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler"
-                                               role="navigation">
-               </div>
-                                                       
-               <div style="height: 10px;">
-                       <!-- space between page number and black footer -->
-               </div>
-               
-       </div><!-- loading -->
-       
-</div><!-- page content -->
index 670fa6a..5471dbd 100644 (file)
@@ -47,7 +47,7 @@
                                                        <th b2b-table-header key="node">Node Name</th>
                                                        <th b2b-table-header key="id">Node ID</th>
                                                        <th b2b-table-header key="address">Address</th>
-                                                       <th b2b-table-header sortable="false"><i class="icon-settings ecd-icon-display"></i></th>
+                                                       <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th>
                                                </tr>
                                        </thead>
 
@@ -59,7 +59,7 @@
                                                        <td b2b-table-body ng-bind="rowData.address" />
                                                        <td b2b-table-body> 
                                                        <div ng-click="ecdapp.viewServicesModalPopup(rowData, ecdapp.datacenter);">
-                                                               <a href="" title="View node services" class="icon-overview ecd-icon-action"></a>
+                                                               <a href="" title="View node services" class="icon-people-preview ecd-icon-action"></a>
                                                        </div>
                                                </td>
                                                </tr>
index 40e8d95..56a7345 100644 (file)
                                                        <th b2b-table-header key="status">Status</th>
                                                        <th b2b-table-header key="node">Node Name</th>
                                                        <th b2b-table-header key="serviceID">Service ID</th>
+                                                       <th b2b-table-header key="serviceID">Tenant</th>
                                                        <th b2b-table-header key="notes">Notes</th>
                                                        <th b2b-table-header key="output">Output</th>
-                                                       <th b2b-table-header sortable="false"><i class="icon-settings ecd-icon-display"></i></th>
+                                                       <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th>
                                                </tr>
                                        </thead>
 
                                                        </td>
                                                        <td b2b-table-body ng-bind="rowData.node" />
                                                        <td b2b-table-body ng-bind="rowData.serviceID" />
+                                                       <td b2b-table-body ng-bind="rowData.tenant" />
                                                        <td b2b-table-body ng-bind="rowData.notes" />
                                                        <td b2b-table-body ng-bind="rowData.output" />
                                                        <td b2b-table-body> 
                                                        <div ng-click="ecdapp.viewHealthHistoryModalPopup(rowData);">
-                                                               <a href="" title="View history" class="icoDocuments-bookmarks ecd-icon-action"></a>
+                                                               <a href="" title="View history" class="icon-datanetwork-history ecd-icon-action"></a>
                                                        </div>
                                                        <div ng-click="ecdapp.deregisterServiceModalPopup(rowData);">
                                                                <a href="" title="Deregister service" class="icon-misc-trash ecd-icon-action"></a>
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/angular-local-storage.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/angular-local-storage.js
new file mode 100644 (file)
index 0000000..a936f14
--- /dev/null
@@ -0,0 +1,592 @@
+/**
+ * An Angular module that gives you access to the browsers local storage
+ * @version v0.7.1 - 2017-06-21
+ * @link https://github.com/grevory/angular-local-storage
+ * @author grevory <greg@gregpike.ca>
+ * @license MIT License, http://www.opensource.org/licenses/MIT
+ */
+(function (window, angular) {
+var isDefined = angular.isDefined,
+  isUndefined = angular.isUndefined,
+  isNumber = angular.isNumber,
+  isObject = angular.isObject,
+  isArray = angular.isArray,
+  isString = angular.isString,
+  extend = angular.extend,
+  toJson = angular.toJson;
+
+angular
+  .module('LocalStorageModule', [])
+  .provider('localStorageService', function() {
+    // You should set a prefix to avoid overwriting any local storage variables from the rest of your app
+    // e.g. localStorageServiceProvider.setPrefix('yourAppName');
+    // With provider you can use config as this:
+    // myApp.config(function (localStorageServiceProvider) {
+    //    localStorageServiceProvider.prefix = 'yourAppName';
+    // });
+    this.prefix = 'ls';
+
+    // You could change web storage type localstorage or sessionStorage
+    this.storageType = 'localStorage';
+
+    // Cookie options (usually in case of fallback)
+    // expiry = Number of days before cookies expire // 0 = Does not expire
+    // path = The web path the cookie represents
+    // secure = Wether the cookies should be secure (i.e only sent on HTTPS requests)
+    this.cookie = {
+      expiry: 30,
+      path: '/',
+      secure: false
+    };
+
+    // Decides wether we should default to cookies if localstorage is not supported.
+    this.defaultToCookie = true;
+
+    // Send signals for each of the following actions?
+    this.notify = {
+      setItem: true,
+      removeItem: false
+    };
+
+    // Setter for the prefix
+    this.setPrefix = function(prefix) {
+      this.prefix = prefix;
+      return this;
+    };
+
+    // Setter for the storageType
+    this.setStorageType = function(storageType) {
+      this.storageType = storageType;
+      return this;
+    };
+    // Setter for defaultToCookie value, default is true.
+    this.setDefaultToCookie = function (shouldDefault) {
+      this.defaultToCookie = !!shouldDefault; // Double-not to make sure it's a bool value.
+      return this;
+    };
+    // Setter for cookie config
+    this.setStorageCookie = function(exp, path, secure) {
+      this.cookie.expiry = exp;
+      this.cookie.path = path;
+      this.cookie.secure = secure;
+      return this;
+    };
+
+    // Setter for cookie domain
+    this.setStorageCookieDomain = function(domain) {
+      this.cookie.domain = domain;
+      return this;
+    };
+
+    // Setter for notification config
+    // itemSet & itemRemove should be booleans
+    this.setNotify = function(itemSet, itemRemove) {
+      this.notify = {
+        setItem: itemSet,
+        removeItem: itemRemove
+      };
+      return this;
+    };
+
+    this.$get = ['$rootScope', '$window', '$document', '$parse','$timeout', function($rootScope, $window, $document, $parse, $timeout) {
+      var self = this;
+      var prefix = self.prefix;
+      var cookie = self.cookie;
+      var notify = self.notify;
+      var storageType = self.storageType;
+      var webStorage;
+
+      // When Angular's $document is not available
+      if (!$document) {
+        $document = document;
+      } else if ($document[0]) {
+        $document = $document[0];
+      }
+
+      // If there is a prefix set in the config lets use that with an appended period for readability
+      if (prefix.substr(-1) !== '.') {
+        prefix = !!prefix ? prefix + '.' : '';
+      }
+      var deriveQualifiedKey = function(key) {
+        return prefix + key;
+      };
+
+      // Removes prefix from the key.
+      var underiveQualifiedKey = function (key) {
+        return key.replace(new RegExp('^' + prefix, 'g'), '');
+      };
+
+      // Check if the key is within our prefix namespace.
+      var isKeyPrefixOurs = function (key) {
+        return key.indexOf(prefix) === 0;
+      };
+
+      // Checks the browser to see if local storage is supported
+      var checkSupport = function () {
+        try {
+          var supported = (storageType in $window && $window[storageType] !== null);
+
+          // When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage
+          // is available, but trying to call .setItem throws an exception.
+          //
+          // "QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage
+          // that exceeded the quota."
+          var key = deriveQualifiedKey('__' + Math.round(Math.random() * 1e7));
+          if (supported) {
+            webStorage = $window[storageType];
+            webStorage.setItem(key, '');
+            webStorage.removeItem(key);
+          }
+
+          return supported;
+        } catch (e) {
+          // Only change storageType to cookies if defaulting is enabled.
+          if (self.defaultToCookie)
+            storageType = 'cookie';
+          $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
+          return false;
+        }
+      };
+      var browserSupportsLocalStorage = checkSupport();
+
+      // Directly adds a value to local storage
+      // If local storage is not available in the browser use cookies
+      // Example use: localStorageService.add('library','angular');
+      var addToLocalStorage = function (key, value, type) {
+        var previousType = getStorageType();
+
+        try {
+          setStorageType(type);
+
+          // Let's convert undefined values to null to get the value consistent
+          if (isUndefined(value)) {
+            value = null;
+          } else {
+            value = toJson(value);
+          }
+
+          // If this browser does not support local storage use cookies
+          if (!browserSupportsLocalStorage && self.defaultToCookie || self.storageType === 'cookie') {
+            if (!browserSupportsLocalStorage) {
+              $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
+            }
+
+            if (notify.setItem) {
+              $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: 'cookie'});
+            }
+            return addToCookies(key, value);
+          }
+
+          try {
+            if (webStorage) {
+              webStorage.setItem(deriveQualifiedKey(key), value);
+            }
+            if (notify.setItem) {
+              $rootScope.$broadcast('LocalStorageModule.notification.setitem', {key: key, newvalue: value, storageType: self.storageType});
+            }
+          } catch (e) {
+            $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
+            return addToCookies(key, value);
+          }
+          return true;
+        } finally {
+          setStorageType(previousType);
+        }
+      };
+
+      // Directly get a value from local storage
+      // Example use: localStorageService.get('library'); // returns 'angular'
+      var getFromLocalStorage = function (key, type) {
+        var previousType = getStorageType();
+
+        try {
+          setStorageType(type);
+
+          if (!browserSupportsLocalStorage && self.defaultToCookie  || self.storageType === 'cookie') {
+            if (!browserSupportsLocalStorage) {
+              $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
+            }
+
+            return getFromCookies(key);
+          }
+
+          var item = webStorage ? webStorage.getItem(deriveQualifiedKey(key)) : null;
+          // angular.toJson will convert null to 'null', so a proper conversion is needed
+          // FIXME not a perfect solution, since a valid 'null' string can't be stored
+          if (!item || item === 'null') {
+            return null;
+          }
+
+          try {
+            return JSON.parse(item);
+          } catch (e) {
+            return item;
+          }
+        } finally {
+          setStorageType(previousType);
+        }
+      };
+
+      // Remove an item from local storage
+      // Example use: localStorageService.remove('library'); // removes the key/value pair of library='angular'
+      //
+      // This is var-arg removal, check the last argument to see if it is a storageType
+      // and set type accordingly before removing.
+      //
+      var removeFromLocalStorage = function () {
+        var previousType = getStorageType();
+
+        try {
+          // can't pop on arguments, so we do this
+          var consumed = 0;
+          if (arguments.length >= 1 &&
+              (arguments[arguments.length - 1] === 'localStorage' ||
+               arguments[arguments.length - 1] === 'sessionStorage')) {
+            consumed = 1;
+            setStorageType(arguments[arguments.length - 1]);
+          }
+
+          var i, key;
+          for (i = 0; i < arguments.length - consumed; i++) {
+            key = arguments[i];
+            if (!browserSupportsLocalStorage && self.defaultToCookie || self.storageType === 'cookie') {
+              if (!browserSupportsLocalStorage) {
+                $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
+              }
+
+              if (notify.removeItem) {
+                $rootScope.$broadcast('LocalStorageModule.notification.removeitem', {key: key, storageType: 'cookie'});
+              }
+              removeFromCookies(key);
+            }
+            else {
+              try {
+                webStorage.removeItem(deriveQualifiedKey(key));
+                if (notify.removeItem) {
+                  $rootScope.$broadcast('LocalStorageModule.notification.removeitem', {
+                    key: key,
+                    storageType: self.storageType
+                  });
+                }
+              } catch (e) {
+                $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
+                removeFromCookies(key);
+              }
+            }
+          }
+        } finally {
+          setStorageType(previousType);
+        }
+      };
+
+      // Return array of keys for local storage
+      // Example use: var keys = localStorageService.keys()
+      var getKeysForLocalStorage = function (type) {
+        var previousType = getStorageType();
+
+        try {
+          setStorageType(type);
+
+          if (!browserSupportsLocalStorage) {
+            $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
+            return [];
+          }
+
+          var prefixLength = prefix.length;
+          var keys = [];
+          for (var key in webStorage) {
+            // Only return keys that are for this app
+            if (key.substr(0, prefixLength) === prefix) {
+              try {
+                keys.push(key.substr(prefixLength));
+              } catch (e) {
+                $rootScope.$broadcast('LocalStorageModule.notification.error', e.Description);
+                return [];
+              }
+            }
+          }
+
+          return keys;
+        } finally {
+          setStorageType(previousType);
+        }
+      };
+
+      // Remove all data for this app from local storage
+      // Also optionally takes a regular expression string and removes the matching key-value pairs
+      // Example use: localStorageService.clearAll();
+      // Should be used mostly for development purposes
+      var clearAllFromLocalStorage = function (regularExpression, type) {
+        var previousType = getStorageType();
+
+        try {
+          setStorageType(type);
+
+          // Setting both regular expressions independently
+          // Empty strings result in catchall RegExp
+          var prefixRegex = !!prefix ? new RegExp('^' + prefix) : new RegExp();
+          var testRegex = !!regularExpression ? new RegExp(regularExpression) : new RegExp();
+
+          if (!browserSupportsLocalStorage && self.defaultToCookie  || self.storageType === 'cookie') {
+            if (!browserSupportsLocalStorage) {
+              $rootScope.$broadcast('LocalStorageModule.notification.warning', 'LOCAL_STORAGE_NOT_SUPPORTED');
+            }
+            return clearAllFromCookies();
+          }
+          if (!browserSupportsLocalStorage && !self.defaultToCookie)
+            return false;
+          var prefixLength = prefix.length;
+
+          for (var key in webStorage) {
+            // Only remove items that are for this app and match the regular expression
+            if (prefixRegex.test(key) && testRegex.test(key.substr(prefixLength))) {
+              try {
+                removeFromLocalStorage(key.substr(prefixLength));
+              } catch (e) {
+                $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
+                return clearAllFromCookies();
+              }
+            }
+          }
+
+          return true;
+        } finally {
+          setStorageType(previousType);
+        }
+      };
+
+      // Checks the browser to see if cookies are supported
+      var browserSupportsCookies = (function() {
+        try {
+          return $window.navigator.cookieEnabled ||
+          ("cookie" in $document && ($document.cookie.length > 0 ||
+            ($document.cookie = "test").indexOf.call($document.cookie, "test") > -1));
+          } catch (e) {
+            $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
+            return false;
+          }
+        }());
+
+        // Directly adds a value to cookies
+        // Typically used as a fallback if local storage is not available in the browser
+        // Example use: localStorageService.cookie.add('library','angular');
+        var addToCookies = function (key, value, daysToExpiry, secure) {
+
+          if (isUndefined(value)) {
+            return false;
+          } else if(isArray(value) || isObject(value)) {
+            value = toJson(value);
+          }
+
+          if (!browserSupportsCookies) {
+            $rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
+            return false;
+          }
+
+          try {
+            var expiry = '',
+            expiryDate = new Date(),
+            cookieDomain = '';
+
+            if (value === null) {
+              // Mark that the cookie has expired one day ago
+              expiryDate.setTime(expiryDate.getTime() + (-1 * 24 * 60 * 60 * 1000));
+              expiry = "; expires=" + expiryDate.toGMTString();
+              value = '';
+            } else if (isNumber(daysToExpiry) && daysToExpiry !== 0) {
+              expiryDate.setTime(expiryDate.getTime() + (daysToExpiry * 24 * 60 * 60 * 1000));
+              expiry = "; expires=" + expiryDate.toGMTString();
+            } else if (cookie.expiry !== 0) {
+              expiryDate.setTime(expiryDate.getTime() + (cookie.expiry * 24 * 60 * 60 * 1000));
+              expiry = "; expires=" + expiryDate.toGMTString();
+            }
+            if (!!key) {
+              var cookiePath = "; path=" + cookie.path;
+              if (cookie.domain) {
+                cookieDomain = "; domain=" + cookie.domain;
+              }
+              /* Providing the secure parameter always takes precedence over config
+               * (allows developer to mix and match secure + non-secure) */
+              if (typeof secure === 'boolean') {
+                  if (secure === true) {
+                      /* We've explicitly specified secure,
+                       * add the secure attribute to the cookie (after domain) */
+                      cookieDomain += "; secure";
+                  }
+                  // else - secure has been supplied but isn't true - so don't set secure flag, regardless of what config says
+              }
+              else if (cookie.secure === true) {
+                  // secure parameter wasn't specified, get default from config
+                  cookieDomain += "; secure";
+              }
+              $document.cookie = deriveQualifiedKey(key) + "=" + encodeURIComponent(value) + expiry + cookiePath + cookieDomain;
+            }
+          } catch (e) {
+            $rootScope.$broadcast('LocalStorageModule.notification.error', e.message);
+            return false;
+          }
+          return true;
+        };
+
+        // Directly get a value from a cookie
+        // Example use: localStorageService.cookie.get('library'); // returns 'angular'
+        var getFromCookies = function (key) {
+          if (!browserSupportsCookies) {
+            $rootScope.$broadcast('LocalStorageModule.notification.error', 'COOKIES_NOT_SUPPORTED');
+            return false;
+          }
+
+          var cookies = $document.cookie && $document.cookie.split(';') || [];
+          for(var i=0; i < cookies.length; i++) {
+            var thisCookie = cookies[i];
+            while (thisCookie.charAt(0) === ' ') {
+              thisCookie = thisCookie.substring(1,thisCookie.length);
+            }
+            if (thisCookie.indexOf(deriveQualifiedKey(key) + '=') === 0) {
+              var storedValues = decodeURIComponent(thisCookie.substring(prefix.length + key.length + 1, thisCookie.length));
+              try {
+                var parsedValue = JSON.parse(storedValues);
+                return typeof(parsedValue) === 'number' ? storedValues : parsedValue;
+              } catch(e) {
+                return storedValues;
+              }
+            }
+          }
+          return null;
+        };
+
+        var removeFromCookies = function (key) {
+          addToCookies(key,null);
+        };
+
+        var clearAllFromCookies = function () {
+          var thisCookie = null;
+          var prefixLength = prefix.length;
+          var cookies = $document.cookie.split(';');
+          for(var i = 0; i < cookies.length; i++) {
+            thisCookie = cookies[i];
+
+            while (thisCookie.charAt(0) === ' ') {
+              thisCookie = thisCookie.substring(1, thisCookie.length);
+            }
+
+            var key = thisCookie.substring(prefixLength, thisCookie.indexOf('='));
+            removeFromCookies(key);
+          }
+        };
+
+        var getStorageType = function() {
+          return storageType;
+        };
+
+        var setStorageType = function(type) {
+          if (type && storageType !== type) {
+            storageType = type;
+            browserSupportsLocalStorage = checkSupport();
+          }
+          return browserSupportsLocalStorage;
+        };
+
+        // Add a listener on scope variable to save its changes to local storage
+        // Return a function which when called cancels binding
+        var bindToScope = function(scope, key, def, lsKey, type) {
+          lsKey = lsKey || key;
+          var value = getFromLocalStorage(lsKey, type);
+
+          if (value === null && isDefined(def)) {
+            value = def;
+          } else if (isObject(value) && isObject(def)) {
+            value = extend(value, def);
+          }
+
+          $parse(key).assign(scope, value);
+
+          return scope.$watch(key, function(newVal) {
+            addToLocalStorage(lsKey, newVal, type);
+          }, isObject(scope[key]));
+        };
+
+        // Add listener to local storage, for update callbacks.
+        if (browserSupportsLocalStorage) {
+            if ($window.addEventListener) {
+                $window.addEventListener("storage", handleStorageChangeCallback, false);
+                $rootScope.$on('$destroy', function() {
+                    $window.removeEventListener("storage", handleStorageChangeCallback);
+                });
+            } else if($window.attachEvent){
+                // attachEvent and detachEvent are proprietary to IE v6-10
+                $window.attachEvent("onstorage", handleStorageChangeCallback);
+                $rootScope.$on('$destroy', function() {
+                    $window.detachEvent("onstorage", handleStorageChangeCallback);
+                });
+            }
+        }
+
+        // Callback handler for storage changed.
+        function handleStorageChangeCallback(e) {
+            if (!e) { e = $window.event; }
+            if (notify.setItem) {
+                if (isString(e.key) && isKeyPrefixOurs(e.key)) {
+                    var key = underiveQualifiedKey(e.key);
+                    // Use timeout, to avoid using $rootScope.$apply.
+                    $timeout(function () {
+                        $rootScope.$broadcast('LocalStorageModule.notification.changed', { key: key, newvalue: e.newValue, storageType: self.storageType });
+                    });
+                }
+            }
+        }
+
+        // Return localStorageService.length
+        // ignore keys that not owned
+        var lengthOfLocalStorage = function(type) {
+          var previousType = getStorageType();
+
+          try {
+            setStorageType(type);
+
+            var count = 0;
+            var storage = $window[storageType];
+            for(var i = 0; i < storage.length; i++) {
+              if(storage.key(i).indexOf(prefix) === 0 ) {
+                count++;
+              }
+            }
+            
+            return count;
+          } finally {
+            setStorageType(previousType);
+          }
+        };
+
+        var changePrefix = function(localStoragePrefix) {
+          prefix = localStoragePrefix;
+        };
+
+        return {
+          isSupported: browserSupportsLocalStorage,
+          getStorageType: getStorageType,
+          setStorageType: setStorageType,
+          setPrefix: changePrefix,
+          set: addToLocalStorage,
+          add: addToLocalStorage, //DEPRECATED
+          get: getFromLocalStorage,
+          keys: getKeysForLocalStorage,
+          remove: removeFromLocalStorage,
+          clearAll: clearAllFromLocalStorage,
+          bind: bindToScope,
+          deriveKey: deriveQualifiedKey,
+          underiveKey: underiveQualifiedKey,
+          length: lengthOfLocalStorage,
+          defaultToCookie: this.defaultToCookie,
+          cookie: {
+            isSupported: browserSupportsCookies,
+            set: addToCookies,
+            add: addToCookies, //DEPRECATED
+            get: getFromCookies,
+            remove: removeFromCookies,
+            clearAll: clearAllFromCookies
+          }
+        };
+      }];
+  });
+})(window, window.angular);
\ No newline at end of file
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.css b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.css
new file mode 100644 (file)
index 0000000..0e713bb
--- /dev/null
@@ -0,0 +1,362 @@
+/*!
+ * ui-select
+ * http://github.com/angular-ui/ui-select
+ * Version: 0.19.7 - 2017-04-15T14:28:36.790Z
+ * License: MIT
+ */
+
+
+/* Style when highlighting a search. */
+.ui-select-highlight {
+  font-weight: bold;
+}
+
+.ui-select-offscreen {
+  clip: rect(0 0 0 0) !important;
+  width: 1px !important;
+  height: 1px !important;
+  border: 0 !important;
+  margin: 0 !important;
+  padding: 0 !important;
+  overflow: hidden !important;
+  position: absolute !important;
+  outline: 0 !important;
+  left: 0px !important;
+  top: 0px !important;
+}
+
+
+.ui-select-choices-row:hover {
+  background-color: #f5f5f5;
+}
+
+/* Select2 theme */
+
+/* Mark invalid Select2 */
+.ng-dirty.ng-invalid > a.select2-choice {
+    border-color: #D44950;
+}
+
+.select2-result-single {
+  padding-left: 0;
+}
+
+.select2-locked > .select2-search-choice-close{
+  display:none;
+}
+
+.select-locked > .ui-select-match-close{
+    display:none;
+}
+
+body > .select2-container.open {
+  z-index: 9999; /* The z-index Select2 applies to the select2-drop */
+}
+
+/* Handle up direction Select2 */
+.ui-select-container[theme="select2"].direction-up .ui-select-match,
+.ui-select-container.select2.direction-up .ui-select-match {
+    border-radius: 4px; /* FIXME hardcoded value :-/ */
+    border-top-left-radius: 0;
+    border-top-right-radius: 0;
+}
+.ui-select-container[theme="select2"].direction-up .ui-select-dropdown,
+.ui-select-container.select2.direction-up .ui-select-dropdown {
+    border-radius: 4px; /* FIXME hardcoded value :-/ */
+    border-bottom-left-radius: 0;
+    border-bottom-right-radius: 0;
+
+    border-top-width: 1px;  /* FIXME hardcoded value :-/ */
+    border-top-style: solid;
+
+    box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
+
+    margin-top: -4px; /* FIXME hardcoded value :-/ */
+}
+.ui-select-container[theme="select2"].direction-up .ui-select-dropdown .select2-search,
+.ui-select-container.select2.direction-up .ui-select-dropdown .select2-search {
+    margin-top: 4px; /* FIXME hardcoded value :-/ */
+}
+.ui-select-container[theme="select2"].direction-up.select2-dropdown-open .ui-select-match,
+.ui-select-container.select2.direction-up.select2-dropdown-open .ui-select-match {
+    border-bottom-color: #5897fb;
+}
+
+.ui-select-container[theme="select2"] .ui-select-dropdown .ui-select-search-hidden,
+.ui-select-container[theme="select2"] .ui-select-dropdown .ui-select-search-hidden input{
+    opacity: 0;
+    height: 0;
+    min-height: 0;
+    padding: 0;
+    margin: 0;
+    border:0;
+}
+
+/* Selectize theme */
+
+/* Helper class to show styles when focus */
+.selectize-input.selectize-focus{
+  border-color: #007FBB !important;
+}
+
+/* Fix input width for Selectize theme */
+.selectize-control.single > .selectize-input > input {
+  width: 100%;
+}
+
+/* Fix line break when there's at least one item selected with the Selectize theme */
+.selectize-control.multi > .selectize-input > input {
+  margin: 0 !important;
+}
+
+/* Fix dropdown width for Selectize theme */
+.selectize-control > .selectize-dropdown {
+  width: 100%;
+}
+
+/* Mark invalid Selectize */
+.ng-dirty.ng-invalid > div.selectize-input {
+    border-color: #D44950;
+}
+
+/* Handle up direction Selectize */
+.ui-select-container[theme="selectize"].direction-up .ui-select-dropdown {
+    box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
+    margin-top: -2px; /* FIXME hardcoded value :-/ */
+}
+
+.ui-select-container[theme="selectize"] input.ui-select-search-hidden{
+    opacity: 0;
+    height: 0;
+    min-height: 0;
+    padding: 0;
+    margin: 0;
+    border:0;
+    width: 0;
+}
+
+/* Bootstrap theme */
+
+/* Helper class to show styles when focus */
+.btn-default-focus {
+  color: #333;
+  background-color: #EBEBEB;
+  border-color: #ADADAD;
+  text-decoration: none;
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+
+.ui-select-bootstrap .ui-select-toggle {
+  position: relative;
+}
+
+.ui-select-bootstrap .ui-select-toggle > .caret {
+  position: absolute;
+  height: 10px;
+  top: 50%;
+  right: 10px;
+  margin-top: -2px;
+}
+
+/* Fix Bootstrap dropdown position when inside a input-group */
+.input-group > .ui-select-bootstrap.dropdown {
+  /* Instead of relative */
+  position: static;
+}
+
+.input-group > .ui-select-bootstrap > input.ui-select-search.form-control {
+  border-radius: 4px; /* FIXME hardcoded value :-/ */
+  border-top-right-radius: 0;
+  border-bottom-right-radius: 0;
+}
+.input-group > .ui-select-bootstrap > input.ui-select-search.form-control.direction-up {
+  border-radius: 4px !important; /* FIXME hardcoded value :-/ */
+  border-top-right-radius: 0 !important;
+  border-bottom-right-radius: 0 !important;
+}
+
+.ui-select-bootstrap .ui-select-search-hidden{
+    opacity: 0;
+    height: 0;
+    min-height: 0;
+    padding: 0;
+    margin: 0;
+    border:0;
+}
+
+.ui-select-bootstrap > .ui-select-match > .btn{
+  /* Instead of center because of .btn */
+  text-align: left !important;
+}
+
+.ui-select-bootstrap > .ui-select-match > .caret {
+  position: absolute;
+  top: 45%;
+  right: 15px;
+}
+
+/* See Scrollable Menu with Bootstrap 3 http://stackoverflow.com/questions/19227496 */
+.ui-select-bootstrap > .ui-select-choices ,.ui-select-bootstrap > .ui-select-no-choice {
+  width: 100%;
+  height: auto;
+  max-height: 200px;
+  overflow-x: hidden;
+  margin-top: -1px;
+}
+
+body > .ui-select-bootstrap.open {
+  z-index: 1000; /* Standard Bootstrap dropdown z-index */
+}
+
+.ui-select-multiple.ui-select-bootstrap {
+  height: auto;
+  padding: 3px 3px 0 3px;
+}
+
+.ui-select-multiple.ui-select-bootstrap input.ui-select-search {
+  background-color: transparent !important; /* To prevent double background when disabled */
+  border: none;
+  outline: none;
+  height: 1.666666em;
+  margin-bottom: 3px;
+}
+
+.ui-select-multiple.ui-select-bootstrap .ui-select-match .close {
+  font-size: 1.6em;
+  line-height: 0.75;
+}
+
+.ui-select-multiple.ui-select-bootstrap .ui-select-match-item {
+  outline: 0;
+  margin: 0 3px 3px 0;
+}
+
+.ui-select-multiple .ui-select-match-item {
+  position: relative;
+}
+
+.ui-select-multiple .ui-select-match-item.dropping .ui-select-match-close {
+  pointer-events: none;
+}
+
+.ui-select-multiple:hover .ui-select-match-item.dropping-before:before {
+  content: "";
+  position: absolute;
+  top: 0;
+  right: 100%;
+  height: 100%;
+  margin-right: 2px;
+  border-left: 1px solid #428bca;
+}
+
+.ui-select-multiple:hover .ui-select-match-item.dropping-after:after {
+  content: "";
+  position: absolute;
+  top: 0;
+  left: 100%;
+  height: 100%;
+  margin-left: 2px;
+  border-right: 1px solid #428bca;
+}
+
+.ui-select-bootstrap .ui-select-choices-row>span {
+    cursor: pointer;
+    display: block;
+    padding: 3px 20px;
+    clear: both;
+    font-weight: 400;
+    line-height: 1.42857143;
+    color: #333;
+    white-space: nowrap;
+}
+
+.ui-select-bootstrap .ui-select-choices-row>span:hover, .ui-select-bootstrap .ui-select-choices-row>span:focus {
+    text-decoration: none;
+    color: #262626;
+    background-color: #f5f5f5;
+}
+
+.ui-select-bootstrap .ui-select-choices-row.active>span {
+    color: #fff;
+    text-decoration: none;
+    outline: 0;
+    background-color: #428bca;
+}
+
+.ui-select-bootstrap .ui-select-choices-row.disabled>span,
+.ui-select-bootstrap .ui-select-choices-row.active.disabled>span {
+    color: #777;
+    cursor: not-allowed;
+    background-color: #fff;
+}
+
+/* fix hide/show angular animation */
+.ui-select-match.ng-hide-add,
+.ui-select-search.ng-hide-add {
+    display: none !important;
+}
+
+/* Mark invalid Bootstrap */
+.ui-select-bootstrap.ng-dirty.ng-invalid > button.btn.ui-select-match {
+    border-color: #D44950;
+}
+
+/* Handle up direction Bootstrap */
+.ui-select-container[theme="bootstrap"].direction-up .ui-select-dropdown {
+    box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
+}
+
+.ui-select-bootstrap .ui-select-match-text {
+    width: 100%;
+    padding-right: 1em;
+}
+.ui-select-bootstrap .ui-select-match-text span {
+    display: inline-block;
+    width: 100%;
+    overflow: hidden;
+}
+.ui-select-bootstrap .ui-select-toggle > a.btn {
+  position: absolute;
+  height: 10px;
+  right: 10px;
+  margin-top: -2px;
+}
+
+/* Spinner */
+.ui-select-refreshing.glyphicon {
+    position: absolute;
+    right: 0;
+    padding: 8px 27px;
+ }
+
+@-webkit-keyframes ui-select-spin {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg);
+  }
+}
+@keyframes ui-select-spin {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg);
+  }
+}
+
+.ui-select-spin {
+  -webkit-animation: ui-select-spin 2s infinite linear;
+  animation: ui-select-spin 2s infinite linear;
+}
+
+.ui-select-refreshing.ng-animate {
+  -webkit-animation: none 0s;
+}
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/external/select.js
new file mode 100644 (file)
index 0000000..5ac4e0b
--- /dev/null
@@ -0,0 +1,2427 @@
+/*!
+ * ui-select
+ * http://github.com/angular-ui/ui-select
+ * Version: 0.19.7 - 2017-04-15T14:28:36.649Z
+ * License: MIT
+ */
+
+
+(function () { 
+"use strict";
+var KEY = {
+    TAB: 9,
+    ENTER: 13,
+    ESC: 27,
+    SPACE: 32,
+    LEFT: 37,
+    UP: 38,
+    RIGHT: 39,
+    DOWN: 40,
+    SHIFT: 16,
+    CTRL: 17,
+    ALT: 18,
+    PAGE_UP: 33,
+    PAGE_DOWN: 34,
+    HOME: 36,
+    END: 35,
+    BACKSPACE: 8,
+    DELETE: 46,
+    COMMAND: 91,
+
+    MAP: { 91 : "COMMAND", 8 : "BACKSPACE" , 9 : "TAB" , 13 : "ENTER" , 16 : "SHIFT" , 17 : "CTRL" , 18 : "ALT" , 19 : "PAUSEBREAK" , 20 : "CAPSLOCK" , 27 : "ESC" , 32 : "SPACE" , 33 : "PAGE_UP", 34 : "PAGE_DOWN" , 35 : "END" , 36 : "HOME" , 37 : "LEFT" , 38 : "UP" , 39 : "RIGHT" , 40 : "DOWN" , 43 : "+" , 44 : "PRINTSCREEN" , 45 : "INSERT" , 46 : "DELETE", 48 : "0" , 49 : "1" , 50 : "2" , 51 : "3" , 52 : "4" , 53 : "5" , 54 : "6" , 55 : "7" , 56 : "8" , 57 : "9" , 59 : ";", 61 : "=" , 65 : "A" , 66 : "B" , 67 : "C" , 68 : "D" , 69 : "E" , 70 : "F" , 71 : "G" , 72 : "H" , 73 : "I" , 74 : "J" , 75 : "K" , 76 : "L", 77 : "M" , 78 : "N" , 79 : "O" , 80 : "P" , 81 : "Q" , 82 : "R" , 83 : "S" , 84 : "T" , 85 : "U" , 86 : "V" , 87 : "W" , 88 : "X" , 89 : "Y" , 90 : "Z", 96 : "0" , 97 : "1" , 98 : "2" , 99 : "3" , 100 : "4" , 101 : "5" , 102 : "6" , 103 : "7" , 104 : "8" , 105 : "9", 106 : "*" , 107 : "+" , 109 : "-" , 110 : "." , 111 : "/", 112 : "F1" , 113 : "F2" , 114 : "F3" , 115 : "F4" , 116 : "F5" , 117 : "F6" , 118 : "F7" , 119 : "F8" , 120 : "F9" , 121 : "F10" , 122 : "F11" , 123 : "F12", 144 : "NUMLOCK" , 145 : "SCROLLLOCK" , 186 : ";" , 187 : "=" , 188 : "," , 189 : "-" , 190 : "." , 191 : "/" , 192 : "`" , 219 : "[" , 220 : "\\" , 221 : "]" , 222 : "'"
+    },
+
+    isControl: function (e) {
+        var k = e.which;
+        switch (k) {
+        case KEY.COMMAND:
+        case KEY.SHIFT:
+        case KEY.CTRL:
+        case KEY.ALT:
+            return true;
+        }
+
+        if (e.metaKey || e.ctrlKey || e.altKey) return true;
+
+        return false;
+    },
+    isFunctionKey: function (k) {
+        k = k.which ? k.which : k;
+        return k >= 112 && k <= 123;
+    },
+    isVerticalMovement: function (k){
+      return ~[KEY.UP, KEY.DOWN].indexOf(k);
+    },
+    isHorizontalMovement: function (k){
+      return ~[KEY.LEFT,KEY.RIGHT,KEY.BACKSPACE,KEY.DELETE].indexOf(k);
+    },
+    toSeparator: function (k) {
+      var sep = {ENTER:"\n",TAB:"\t",SPACE:" "}[k];
+      if (sep) return sep;
+      // return undefined for special keys other than enter, tab or space.
+      // no way to use them to cut strings.
+      return KEY[k] ? undefined : k;
+    }
+  };
+
+function isNil(value) {
+  return angular.isUndefined(value) || value === null;
+}
+
+/**
+ * Add querySelectorAll() to jqLite.
+ *
+ * jqLite find() is limited to lookups by tag name.
+ * TODO This will change with future versions of AngularJS, to be removed when this happens
+ *
+ * See jqLite.find - why not use querySelectorAll? https://github.com/angular/angular.js/issues/3586
+ * See feat(jqLite): use querySelectorAll instead of getElementsByTagName in jqLite.find https://github.com/angular/angular.js/pull/3598
+ */
+if (angular.element.prototype.querySelectorAll === undefined) {
+  angular.element.prototype.querySelectorAll = function(selector) {
+    return angular.element(this[0].querySelectorAll(selector));
+  };
+}
+
+/**
+ * Add closest() to jqLite.
+ */
+if (angular.element.prototype.closest === undefined) {
+  angular.element.prototype.closest = function( selector) {
+    var elem = this[0];
+    var matchesSelector = elem.matches || elem.webkitMatchesSelector || elem.mozMatchesSelector || elem.msMatchesSelector;
+
+    while (elem) {
+      if (matchesSelector.bind(elem)(selector)) {
+        return elem;
+      } else {
+        elem = elem.parentElement;
+      }
+    }
+    return false;
+  };
+}
+
+var latestId = 0;
+
+var uis = angular.module('ui.select', [])
+
+.constant('uiSelectConfig', {
+  theme: 'bootstrap',
+  searchEnabled: true,
+  sortable: false,
+  placeholder: '', // Empty by default, like HTML tag <select>
+  refreshDelay: 1000, // In milliseconds
+  closeOnSelect: true,
+  skipFocusser: false,
+  dropdownPosition: 'auto',
+  removeSelected: true,
+  resetSearchInput: true,
+  generateId: function() {
+    return latestId++;
+  },
+  appendToBody: false,
+  spinnerEnabled: false,
+  spinnerClass: 'glyphicon glyphicon-refresh ui-select-spin',
+  backspaceReset: true
+})
+
+// See Rename minErr and make it accessible from outside https://github.com/angular/angular.js/issues/6913
+.service('uiSelectMinErr', function() {
+  var minErr = angular.$$minErr('ui.select');
+  return function() {
+    var error = minErr.apply(this, arguments);
+    var message = error.message.replace(new RegExp('\nhttp://errors.angularjs.org/.*'), '');
+    return new Error(message);
+  };
+})
+
+// Recreates old behavior of ng-transclude. Used internally.
+.directive('uisTranscludeAppend', function () {
+  return {
+    link: function (scope, element, attrs, ctrl, transclude) {
+        transclude(scope, function (clone) {
+          element.append(clone);
+        });
+      }
+    };
+})
+
+/**
+ * Highlights text that matches $select.search.
+ *
+ * Taken from AngularUI Bootstrap Typeahead
+ * See https://github.com/angular-ui/bootstrap/blob/0.10.0/src/typeahead/typeahead.js#L340
+ */
+.filter('highlight', function() {
+  function escapeRegexp(queryToEscape) {
+    return ('' + queryToEscape).replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
+  }
+
+  return function(matchItem, query) {
+    return query && matchItem ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<span class="ui-select-highlight">$&</span>') : matchItem;
+  };
+})
+
+/**
+ * A read-only equivalent of jQuery's offset function: http://api.jquery.com/offset/
+ *
+ * Taken from AngularUI Bootstrap Position:
+ * See https://github.com/angular-ui/bootstrap/blob/master/src/position/position.js#L70
+ */
+.factory('uisOffset',
+  ['$document', '$window',
+  function ($document, $window) {
+
+  return function(element) {
+    var boundingClientRect = element[0].getBoundingClientRect();
+    return {
+      width: boundingClientRect.width || element.prop('offsetWidth'),
+      height: boundingClientRect.height || element.prop('offsetHeight'),
+      top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop),
+      left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft)
+    };
+  };
+}]);
+
+/**
+ * Debounces functions
+ *
+ * Taken from UI Bootstrap $$debounce source code
+ * See https://github.com/angular-ui/bootstrap/blob/master/src/debounce/debounce.js
+ *
+ */
+uis.factory('$$uisDebounce', ['$timeout', function($timeout) {
+  return function(callback, debounceTime) {
+    var timeoutPromise;
+
+    return function() {
+      var self = this;
+      var args = Array.prototype.slice.call(arguments);
+      if (timeoutPromise) {
+        $timeout.cancel(timeoutPromise);
+      }
+
+      timeoutPromise = $timeout(function() {
+        callback.apply(self, args);
+      }, debounceTime);
+    };
+  };
+}]);
+
+uis.directive('uiSelectChoices',
+  ['uiSelectConfig', 'uisRepeatParser', 'uiSelectMinErr', '$compile', '$window',
+  function(uiSelectConfig, RepeatParser, uiSelectMinErr, $compile, $window) {
+
+  return {
+    restrict: 'EA',
+    require: '^uiSelect',
+    replace: true,
+    transclude: true,
+    templateUrl: function(tElement) {
+      // Needed so the uiSelect can detect the transcluded content
+      tElement.addClass('ui-select-choices');
+
+      // Gets theme attribute from parent (ui-select)
+      var theme = tElement.parent().attr('theme') || uiSelectConfig.theme;
+      return theme + '/choices.tpl.html';
+    },
+
+    compile: function(tElement, tAttrs) {
+
+      if (!tAttrs.repeat) throw uiSelectMinErr('repeat', "Expected 'repeat' expression.");
+
+      // var repeat = RepeatParser.parse(attrs.repeat);
+      var groupByExp = tAttrs.groupBy;
+      var groupFilterExp = tAttrs.groupFilter;
+
+      if (groupByExp) {
+        var groups = tElement.querySelectorAll('.ui-select-choices-group');
+        if (groups.length !== 1) throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-group but got '{0}'.", groups.length);
+        groups.attr('ng-repeat', RepeatParser.getGroupNgRepeatExpression());
+      }
+
+      var parserResult = RepeatParser.parse(tAttrs.repeat);
+
+      var choices = tElement.querySelectorAll('.ui-select-choices-row');
+      if (choices.length !== 1) {
+        throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-row but got '{0}'.", choices.length);
+      }
+
+      choices.attr('ng-repeat', parserResult.repeatExpression(groupByExp))
+             .attr('ng-if', '$select.open'); //Prevent unnecessary watches when dropdown is closed
+
+
+      var rowsInner = tElement.querySelectorAll('.ui-select-choices-row-inner');
+      if (rowsInner.length !== 1) {
+        throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-row-inner but got '{0}'.", rowsInner.length);
+      }
+      rowsInner.attr('uis-transclude-append', ''); //Adding uisTranscludeAppend directive to row element after choices element has ngRepeat
+
+      // If IE8 then need to target rowsInner to apply the ng-click attr as choices will not capture the event.
+      var clickTarget = $window.document.addEventListener ? choices : rowsInner;
+      clickTarget.attr('ng-click', '$select.select(' + parserResult.itemName + ',$select.skipFocusser,$event)');
+
+      return function link(scope, element, attrs, $select) {
+
+
+        $select.parseRepeatAttr(attrs.repeat, groupByExp, groupFilterExp); //Result ready at $select.parserResult
+        $select.disableChoiceExpression = attrs.uiDisableChoice;
+        $select.onHighlightCallback = attrs.onHighlight;
+        $select.minimumInputLength = parseInt(attrs.minimumInputLength) || 0;
+        $select.dropdownPosition = attrs.position ? attrs.position.toLowerCase() : uiSelectConfig.dropdownPosition;
+
+        scope.$watch('$select.search', function(newValue) {
+          if(newValue && !$select.open && $select.multiple) $select.activate(false, true);
+          $select.activeIndex = $select.tagging.isActivated ? -1 : 0;
+          if (!attrs.minimumInputLength || $select.search.length >= attrs.minimumInputLength) {
+            $select.refresh(attrs.refresh);
+          } else {
+            $select.items = [];
+          }
+        });
+
+        attrs.$observe('refreshDelay', function() {
+          // $eval() is needed otherwise we get a string instead of a number
+          var refreshDelay = scope.$eval(attrs.refreshDelay);
+          $select.refreshDelay = refreshDelay !== undefined ? refreshDelay : uiSelectConfig.refreshDelay;
+        });
+
+        scope.$watch('$select.open', function(open) {
+          if (open) {
+            tElement.attr('role', 'listbox');
+            $select.refresh(attrs.refresh);
+          } else {
+            element.removeAttr('role');
+          }
+        });
+      };
+    }
+  };
+}]);
+
+/**
+ * Contains ui-select "intelligence".
+ *
+ * The goal is to limit dependency on the DOM whenever possible and
+ * put as much logic in the controller (instead of the link functions) as possible so it can be easily tested.
+ */
+uis.controller('uiSelectCtrl',
+  ['$scope', '$element', '$timeout', '$filter', '$$uisDebounce', 'uisRepeatParser', 'uiSelectMinErr', 'uiSelectConfig', '$parse', '$injector', '$window',
+  function($scope, $element, $timeout, $filter, $$uisDebounce, RepeatParser, uiSelectMinErr, uiSelectConfig, $parse, $injector, $window) {
+
+  var ctrl = this;
+
+  var EMPTY_SEARCH = '';
+
+  ctrl.placeholder = uiSelectConfig.placeholder;
+  ctrl.searchEnabled = uiSelectConfig.searchEnabled;
+  ctrl.sortable = uiSelectConfig.sortable;
+  ctrl.refreshDelay = uiSelectConfig.refreshDelay;
+  ctrl.paste = uiSelectConfig.paste;
+  ctrl.resetSearchInput = uiSelectConfig.resetSearchInput;
+  ctrl.refreshing = false;
+  ctrl.spinnerEnabled = uiSelectConfig.spinnerEnabled;
+  ctrl.spinnerClass = uiSelectConfig.spinnerClass;
+  ctrl.removeSelected = uiSelectConfig.removeSelected; //If selected item(s) should be removed from dropdown list
+  ctrl.closeOnSelect = true; //Initialized inside uiSelect directive link function
+  ctrl.skipFocusser = false; //Set to true to avoid returning focus to ctrl when item is selected
+  ctrl.search = EMPTY_SEARCH;
+
+  ctrl.activeIndex = 0; //Dropdown of choices
+  ctrl.items = []; //All available choices
+
+  ctrl.open = false;
+  ctrl.focus = false;
+  ctrl.disabled = false;
+  ctrl.selected = undefined;
+
+  ctrl.dropdownPosition = 'auto';
+
+  ctrl.focusser = undefined; //Reference to input element used to handle focus events
+  ctrl.multiple = undefined; // Initialized inside uiSelect directive link function
+  ctrl.disableChoiceExpression = undefined; // Initialized inside uiSelectChoices directive link function
+  ctrl.tagging = {isActivated: false, fct: undefined};
+  ctrl.taggingTokens = {isActivated: false, tokens: undefined};
+  ctrl.lockChoiceExpression = undefined; // Initialized inside uiSelectMatch directive link function
+  ctrl.clickTriggeredSelect = false;
+  ctrl.$filter = $filter;
+  ctrl.$element = $element;
+
+  // Use $injector to check for $animate and store a reference to it
+  ctrl.$animate = (function () {
+    try {
+      return $injector.get('$animate');
+    } catch (err) {
+      // $animate does not exist
+      return null;
+    }
+  })();
+
+  ctrl.searchInput = $element.querySelectorAll('input.ui-select-search');
+  if (ctrl.searchInput.length !== 1) {
+    throw uiSelectMinErr('searchInput', "Expected 1 input.ui-select-search but got '{0}'.", ctrl.searchInput.length);
+  }
+
+  ctrl.isEmpty = function() {
+    return isNil(ctrl.selected) || ctrl.selected === '' || (ctrl.multiple && ctrl.selected.length === 0);
+  };
+
+  function _findIndex(collection, predicate, thisArg){
+    if (collection.findIndex){
+      return collection.findIndex(predicate, thisArg);
+    } else {
+      var list = Object(collection);
+      var length = list.length >>> 0;
+      var value;
+
+      for (var i = 0; i < length; i++) {
+        value = list[i];
+        if (predicate.call(thisArg, value, i, list)) {
+          return i;
+        }
+      }
+      return -1;
+    }
+  }
+
+  // Most of the time the user does not want to empty the search input when in typeahead mode
+  function _resetSearchInput() {
+    if (ctrl.resetSearchInput) {
+      ctrl.search = EMPTY_SEARCH;
+      //reset activeIndex
+      if (ctrl.selected && ctrl.items.length && !ctrl.multiple) {
+        ctrl.activeIndex = _findIndex(ctrl.items, function(item){
+          return angular.equals(this, item);
+        }, ctrl.selected);
+      }
+    }
+  }
+
+    function _groupsFilter(groups, groupNames) {
+      var i, j, result = [];
+      for(i = 0; i < groupNames.length ;i++){
+        for(j = 0; j < groups.length ;j++){
+          if(groups[j].name == [groupNames[i]]){
+            result.push(groups[j]);
+          }
+        }
+      }
+      return result;
+    }
+
+  // When the user clicks on ui-select, displays the dropdown list
+  ctrl.activate = function(initSearchValue, avoidReset) {
+    if (!ctrl.disabled  && !ctrl.open) {
+      if(!avoidReset) _resetSearchInput();
+
+      $scope.$broadcast('uis:activate');
+      ctrl.open = true;
+      ctrl.activeIndex = ctrl.activeIndex >= ctrl.items.length ? 0 : ctrl.activeIndex;
+      // ensure that the index is set to zero for tagging variants
+      // that where first option is auto-selected
+      if ( ctrl.activeIndex === -1 && ctrl.taggingLabel !== false ) {
+        ctrl.activeIndex = 0;
+      }
+
+      var container = $element.querySelectorAll('.ui-select-choices-content');
+      var searchInput = $element.querySelectorAll('.ui-select-search');
+      if (ctrl.$animate && ctrl.$animate.on && ctrl.$animate.enabled(container[0])) {
+        var animateHandler = function(elem, phase) {
+          if (phase === 'start' && ctrl.items.length === 0) {
+            // Only focus input after the animation has finished
+            ctrl.$animate.off('removeClass', searchInput[0], animateHandler);
+            $timeout(function () {
+              ctrl.focusSearchInput(initSearchValue);
+            });
+          } else if (phase === 'close') {
+            // Only focus input after the animation has finished
+            ctrl.$animate.off('enter', container[0], animateHandler);
+            $timeout(function () {
+              ctrl.focusSearchInput(initSearchValue);
+            });
+          }
+        };
+
+        if (ctrl.items.length > 0) {
+          ctrl.$animate.on('enter', container[0], animateHandler);
+        } else {
+          ctrl.$animate.on('removeClass', searchInput[0], animateHandler);
+        }
+      } else {
+        $timeout(function () {
+          ctrl.focusSearchInput(initSearchValue);
+          if(!ctrl.tagging.isActivated && ctrl.items.length > 1) {
+            _ensureHighlightVisible();
+          }
+        });
+      }
+    }
+    else if (ctrl.open && !ctrl.searchEnabled) {
+      // Close the selection if we don't have search enabled, and we click on the select again
+      ctrl.close();
+    }
+  };
+
+  ctrl.focusSearchInput = function (initSearchValue) {
+    ctrl.search = initSearchValue || ctrl.search;
+    ctrl.searchInput[0].focus();
+  };
+
+  ctrl.findGroupByName = function(name) {
+    return ctrl.groups && ctrl.groups.filter(function(group) {
+      return group.name === name;
+    })[0];
+  };
+
+  ctrl.parseRepeatAttr = function(repeatAttr, groupByExp, groupFilterExp) {
+    function updateGroups(items) {
+      var groupFn = $scope.$eval(groupByExp);
+      ctrl.groups = [];
+      angular.forEach(items, function(item) {
+        var groupName = angular.isFunction(groupFn) ? groupFn(item) : item[groupFn];
+        var group = ctrl.findGroupByName(groupName);
+        if(group) {
+          group.items.push(item);
+        }
+        else {
+          ctrl.groups.push({name: groupName, items: [item]});
+        }
+      });
+      if(groupFilterExp){
+        var groupFilterFn = $scope.$eval(groupFilterExp);
+        if( angular.isFunction(groupFilterFn)){
+          ctrl.groups = groupFilterFn(ctrl.groups);
+        } else if(angular.isArray(groupFilterFn)){
+          ctrl.groups = _groupsFilter(ctrl.groups, groupFilterFn);
+        }
+      }
+      ctrl.items = [];
+      ctrl.groups.forEach(function(group) {
+        ctrl.items = ctrl.items.concat(group.items);
+      });
+    }
+
+    function setPlainItems(items) {
+      ctrl.items = items || [];
+    }
+
+    ctrl.setItemsFn = groupByExp ? updateGroups : setPlainItems;
+
+    ctrl.parserResult = RepeatParser.parse(repeatAttr);
+
+    ctrl.isGrouped = !!groupByExp;
+    ctrl.itemProperty = ctrl.parserResult.itemName;
+
+    //If collection is an Object, convert it to Array
+
+    var originalSource = ctrl.parserResult.source;
+
+    //When an object is used as source, we better create an array and use it as 'source'
+    var createArrayFromObject = function(){
+      var origSrc = originalSource($scope);
+      $scope.$uisSource = Object.keys(origSrc).map(function(v){
+        var result = {};
+        result[ctrl.parserResult.keyName] = v;
+        result.value = origSrc[v];
+        return result;
+      });
+    };
+
+    if (ctrl.parserResult.keyName){ // Check for (key,value) syntax
+      createArrayFromObject();
+      ctrl.parserResult.source = $parse('$uisSource' + ctrl.parserResult.filters);
+      $scope.$watch(originalSource, function(newVal, oldVal){
+        if (newVal !== oldVal) createArrayFromObject();
+      }, true);
+    }
+
+    ctrl.refreshItems = function (data){
+      data = data || ctrl.parserResult.source($scope);
+      var selectedItems = ctrl.selected;
+      //TODO should implement for single mode removeSelected
+      if (ctrl.isEmpty() || (angular.isArray(selectedItems) && !selectedItems.length) || !ctrl.multiple || !ctrl.removeSelected) {
+        ctrl.setItemsFn(data);
+      }else{
+        if ( data !== undefined && data !== null ) {
+          var filteredItems = data.filter(function(i) {
+            return angular.isArray(selectedItems) ? selectedItems.every(function(selectedItem) {
+              return !angular.equals(i, selectedItem);
+            }) : !angular.equals(i, selectedItems);
+          });
+          ctrl.setItemsFn(filteredItems);
+        }
+      }
+      if (ctrl.dropdownPosition === 'auto' || ctrl.dropdownPosition === 'up'){
+        $scope.calculateDropdownPos();
+      }
+      $scope.$broadcast('uis:refresh');
+    };
+
+    // See https://github.com/angular/angular.js/blob/v1.2.15/src/ng/directive/ngRepeat.js#L259
+    $scope.$watchCollection(ctrl.parserResult.source, function(items) {
+      if (items === undefined || items === null) {
+        // If the user specifies undefined or null => reset the collection
+        // Special case: items can be undefined if the user did not initialized the collection on the scope
+        // i.e $scope.addresses = [] is missing
+        ctrl.items = [];
+      } else {
+        if (!angular.isArray(items)) {
+          throw uiSelectMinErr('items', "Expected an array but got '{0}'.", items);
+        } else {
+          //Remove already selected items (ex: while searching)
+          //TODO Should add a test
+          ctrl.refreshItems(items);
+
+          //update the view value with fresh data from items, if there is a valid model value
+          if(angular.isDefined(ctrl.ngModel.$modelValue)) {
+            ctrl.ngModel.$modelValue = null; //Force scope model value and ngModel value to be out of sync to re-run formatters
+          }
+        }
+      }
+    });
+
+  };
+
+  var _refreshDelayPromise;
+
+  /**
+   * Typeahead mode: lets the user refresh the collection using his own function.
+   *
+   * See Expose $select.search for external / remote filtering https://github.com/angular-ui/ui-select/pull/31
+   */
+  ctrl.refresh = function(refreshAttr) {
+    if (refreshAttr !== undefined) {
+      // Debounce
+      // See https://github.com/angular-ui/bootstrap/blob/0.10.0/src/typeahead/typeahead.js#L155
+      // FYI AngularStrap typeahead does not have debouncing: https://github.com/mgcrea/angular-strap/blob/v2.0.0-rc.4/src/typeahead/typeahead.js#L177
+      if (_refreshDelayPromise) {
+        $timeout.cancel(_refreshDelayPromise);
+      }
+      _refreshDelayPromise = $timeout(function() {
+        if ($scope.$select.search.length >= $scope.$select.minimumInputLength) {
+          var refreshPromise = $scope.$eval(refreshAttr);
+          if (refreshPromise && angular.isFunction(refreshPromise.then) && !ctrl.refreshing) {
+            ctrl.refreshing = true;
+            refreshPromise.finally(function() {
+              ctrl.refreshing = false;
+            });
+          }
+        }
+      }, ctrl.refreshDelay);
+    }
+  };
+
+  ctrl.isActive = function(itemScope) {
+    if ( !ctrl.open ) {
+      return false;
+    }
+    var itemIndex = ctrl.items.indexOf(itemScope[ctrl.itemProperty]);
+    var isActive =  itemIndex == ctrl.activeIndex;
+
+    if ( !isActive || itemIndex < 0 ) {
+      return false;
+    }
+
+    if (isActive && !angular.isUndefined(ctrl.onHighlightCallback)) {
+      itemScope.$eval(ctrl.onHighlightCallback);
+    }
+
+    return isActive;
+  };
+
+  var _isItemSelected = function (item) {
+    return (ctrl.selected && angular.isArray(ctrl.selected) &&
+        ctrl.selected.filter(function (selection) { return angular.equals(selection, item); }).length > 0);
+  };
+
+  var disabledItems = [];
+
+  function _updateItemDisabled(item, isDisabled) {
+    var disabledItemIndex = disabledItems.indexOf(item);
+    if (isDisabled && disabledItemIndex === -1) {
+      disabledItems.push(item);
+    }
+
+    if (!isDisabled && disabledItemIndex > -1) {
+      disabledItems.splice(disabledItemIndex, 1);
+    }
+  }
+
+  function _isItemDisabled(item) {
+    return disabledItems.indexOf(item) > -1;
+  }
+
+  ctrl.isDisabled = function(itemScope) {
+
+    if (!ctrl.open) return;
+
+    var item = itemScope[ctrl.itemProperty];
+    var itemIndex = ctrl.items.indexOf(item);
+    var isDisabled = false;
+
+    if (itemIndex >= 0 && (angular.isDefined(ctrl.disableChoiceExpression) || ctrl.multiple)) {
+
+      if (item.isTag) return false;
+
+      if (ctrl.multiple) {
+        isDisabled = _isItemSelected(item);
+      }
+
+      if (!isDisabled && angular.isDefined(ctrl.disableChoiceExpression)) {
+        isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression));
+      }
+
+      _updateItemDisabled(item, isDisabled);
+    }
+
+    return isDisabled;
+  };
+
+
+  // When the user selects an item with ENTER or clicks the dropdown
+  ctrl.select = function(item, skipFocusser, $event) {
+    if (isNil(item) || !_isItemDisabled(item)) {
+
+      if ( ! ctrl.items && ! ctrl.search && ! ctrl.tagging.isActivated) return;
+
+      if (!item || !_isItemDisabled(item)) {
+        // if click is made on existing item, prevent from tagging, ctrl.search does not matter
+        ctrl.clickTriggeredSelect = false;
+        if($event && ($event.type === 'click' || $event.type === 'touchend') && item)
+          ctrl.clickTriggeredSelect = true;
+
+        if(ctrl.tagging.isActivated && ctrl.clickTriggeredSelect === false) {
+          // if taggingLabel is disabled and item is undefined we pull from ctrl.search
+          if ( ctrl.taggingLabel === false ) {
+            if ( ctrl.activeIndex < 0 ) {
+              if (item === undefined) {
+                item = ctrl.tagging.fct !== undefined ? ctrl.tagging.fct(ctrl.search) : ctrl.search;
+              }
+              if (!item || angular.equals( ctrl.items[0], item ) ) {
+                return;
+              }
+            } else {
+              // keyboard nav happened first, user selected from dropdown
+              item = ctrl.items[ctrl.activeIndex];
+            }
+          } else {
+            // tagging always operates at index zero, taggingLabel === false pushes
+            // the ctrl.search value without having it injected
+            if ( ctrl.activeIndex === 0 ) {
+              // ctrl.tagging pushes items to ctrl.items, so we only have empty val
+              // for `item` if it is a detected duplicate
+              if ( item === undefined ) return;
+
+              // create new item on the fly if we don't already have one;
+              // use tagging function if we have one
+              if ( ctrl.tagging.fct !== undefined && typeof item === 'string' ) {
+                item = ctrl.tagging.fct(item);
+                if (!item) return;
+              // if item type is 'string', apply the tagging label
+              } else if ( typeof item === 'string' ) {
+                // trim the trailing space
+                item = item.replace(ctrl.taggingLabel,'').trim();
+              }
+            }
+          }
+          // search ctrl.selected for dupes potentially caused by tagging and return early if found
+          if (_isItemSelected(item)) {
+            ctrl.close(skipFocusser);
+            return;
+          }
+        }
+        _resetSearchInput();
+        $scope.$broadcast('uis:select', item);
+
+        if (ctrl.closeOnSelect) {
+          ctrl.close(skipFocusser);
+        }
+      }
+    }
+  };
+
+  // Closes the dropdown
+  ctrl.close = function(skipFocusser) {
+    if (!ctrl.open) return;
+    if (ctrl.ngModel && ctrl.ngModel.$setTouched) ctrl.ngModel.$setTouched();
+    ctrl.open = false;
+    _resetSearchInput();
+    $scope.$broadcast('uis:close', skipFocusser);
+
+  };
+
+  ctrl.setFocus = function(){
+    if (!ctrl.focus) ctrl.focusInput[0].focus();
+  };
+
+  ctrl.clear = function($event) {
+    ctrl.select(null);
+    $event.stopPropagation();
+    $timeout(function() {
+      ctrl.focusser[0].focus();
+    }, 0, false);
+  };
+
+  // Toggle dropdown
+  ctrl.toggle = function(e) {
+    if (ctrl.open) {
+      ctrl.close();
+      e.preventDefault();
+      e.stopPropagation();
+    } else {
+      ctrl.activate();
+    }
+  };
+
+  // Set default function for locked choices - avoids unnecessary
+  // logic if functionality is not being used
+  ctrl.isLocked = function () {
+    return false;
+  };
+
+  $scope.$watch(function () {
+    return angular.isDefined(ctrl.lockChoiceExpression) && ctrl.lockChoiceExpression !== "";
+  }, _initaliseLockedChoices);
+
+  function _initaliseLockedChoices(doInitalise) {
+    if(!doInitalise) return;
+
+    var lockedItems = [];
+
+    function _updateItemLocked(item, isLocked) {
+      var lockedItemIndex = lockedItems.indexOf(item);
+      if (isLocked && lockedItemIndex === -1) {
+        lockedItems.push(item);
+        }
+
+      if (!isLocked && lockedItemIndex > -1) {
+        lockedItems.splice(lockedItemIndex, 1);
+      }
+    }
+
+    function _isItemlocked(item) {
+      return lockedItems.indexOf(item) > -1;
+    }
+
+    ctrl.isLocked = function (itemScope, itemIndex) {
+      var isLocked = false,
+          item = ctrl.selected[itemIndex];
+
+      if(item) {
+        if (itemScope) {
+          isLocked = !!(itemScope.$eval(ctrl.lockChoiceExpression));
+          _updateItemLocked(item, isLocked);
+        } else {
+          isLocked = _isItemlocked(item);
+        }
+      }
+
+      return isLocked;
+    };
+  }
+
+
+  var sizeWatch = null;
+  var updaterScheduled = false;
+  ctrl.sizeSearchInput = function() {
+
+    var input = ctrl.searchInput[0],
+        container = ctrl.$element[0],
+        calculateContainerWidth = function() {
+          // Return the container width only if the search input is visible
+          return container.clientWidth * !!input.offsetParent;
+        },
+        updateIfVisible = function(containerWidth) {
+          if (containerWidth === 0) {
+            return false;
+          }
+          var inputWidth = containerWidth - input.offsetLeft;
+          if (inputWidth < 50) inputWidth = containerWidth;
+          ctrl.searchInput.css('width', inputWidth+'px');
+          return true;
+        };
+
+    ctrl.searchInput.css('width', '10px');
+    $timeout(function() { //Give tags time to render correctly
+      if (sizeWatch === null && !updateIfVisible(calculateContainerWidth())) {
+        sizeWatch = $scope.$watch(function() {
+          if (!updaterScheduled) {
+            updaterScheduled = true;
+            $scope.$$postDigest(function() {
+              updaterScheduled = false;
+              if (updateIfVisible(calculateContainerWidth())) {
+                sizeWatch();
+                sizeWatch = null;
+              }
+            });
+          }
+        }, angular.noop);
+      }
+    });
+  };
+
+  function _handleDropDownSelection(key) {
+    var processed = true;
+    switch (key) {
+      case KEY.DOWN:
+        if (!ctrl.open && ctrl.multiple) ctrl.activate(false, true); //In case its the search input in 'multiple' mode
+        else if (ctrl.activeIndex < ctrl.items.length - 1) {
+          var idx = ++ctrl.activeIndex;
+          while(_isItemDisabled(ctrl.items[idx]) && idx < ctrl.items.length) {
+            ctrl.activeIndex = ++idx;
+          }
+        }
+        break;
+      case KEY.UP:
+        var minActiveIndex = (ctrl.search.length === 0 && ctrl.tagging.isActivated) ? -1 : 0;
+        if (!ctrl.open && ctrl.multiple) ctrl.activate(false, true); //In case its the search input in 'multiple' mode
+        else if (ctrl.activeIndex > minActiveIndex) {
+          var idxmin = --ctrl.activeIndex;
+          while(_isItemDisabled(ctrl.items[idxmin]) && idxmin > minActiveIndex) {
+            ctrl.activeIndex = --idxmin;
+          }
+        }
+        break;
+      case KEY.TAB:
+        if (!ctrl.multiple || ctrl.open) ctrl.select(ctrl.items[ctrl.activeIndex], true);
+        break;
+      case KEY.ENTER:
+        if(ctrl.open && (ctrl.tagging.isActivated || ctrl.activeIndex >= 0)){
+          ctrl.select(ctrl.items[ctrl.activeIndex], ctrl.skipFocusser); // Make sure at least one dropdown item is highlighted before adding if not in tagging mode
+        } else {
+          ctrl.activate(false, true); //In case its the search input in 'multiple' mode
+        }
+        break;
+      case KEY.ESC:
+        ctrl.close();
+        break;
+      default:
+        processed = false;
+    }
+    return processed;
+  }
+
+  // Bind to keyboard shortcuts
+  ctrl.searchInput.on('keydown', function(e) {
+
+    var key = e.which;
+
+    if (~[KEY.ENTER,KEY.ESC].indexOf(key)){
+      e.preventDefault();
+      e.stopPropagation();
+    }
+
+    $scope.$apply(function() {
+
+      var tagged = false;
+
+      if (ctrl.items.length > 0 || ctrl.tagging.isActivated) {
+        if(!_handleDropDownSelection(key) && !ctrl.searchEnabled) {
+          e.preventDefault();
+          e.stopPropagation();
+        }
+        if ( ctrl.taggingTokens.isActivated ) {
+          for (var i = 0; i < ctrl.taggingTokens.tokens.length; i++) {
+            if ( ctrl.taggingTokens.tokens[i] === KEY.MAP[e.keyCode] ) {
+              // make sure there is a new value to push via tagging
+              if ( ctrl.search.length > 0 ) {
+                tagged = true;
+              }
+            }
+          }
+          if ( tagged ) {
+            $timeout(function() {
+              ctrl.searchInput.triggerHandler('tagged');
+              var newItem = ctrl.search.replace(KEY.MAP[e.keyCode],'').trim();
+              if ( ctrl.tagging.fct ) {
+                newItem = ctrl.tagging.fct( newItem );
+              }
+              if (newItem) ctrl.select(newItem, true);
+            });
+          }
+        }
+      }
+
+    });
+
+    if(KEY.isVerticalMovement(key) && ctrl.items.length > 0){
+      _ensureHighlightVisible();
+    }
+
+    if (key === KEY.ENTER || key === KEY.ESC) {
+      e.preventDefault();
+      e.stopPropagation();
+    }
+
+  });
+
+  ctrl.searchInput.on('paste', function (e) {
+    var data;
+
+    if (window.clipboardData && window.clipboardData.getData) { // IE
+      data = window.clipboardData.getData('Text');
+    } else {
+      data = (e.originalEvent || e).clipboardData.getData('text/plain');
+    }
+
+    // Prepend the current input field text to the paste buffer.
+    data = ctrl.search + data;
+
+    if (data && data.length > 0) {
+      // If tagging try to split by tokens and add items
+      if (ctrl.taggingTokens.isActivated) {
+        var items = [];
+        for (var i = 0; i < ctrl.taggingTokens.tokens.length; i++) {  // split by first token that is contained in data
+          var separator = KEY.toSeparator(ctrl.taggingTokens.tokens[i]) || ctrl.taggingTokens.tokens[i];
+          if (data.indexOf(separator) > -1) {
+            items = data.split(separator);
+            break;  // only split by one token
+          }
+        }
+        if (items.length === 0) {
+          items = [data];
+        }
+        var oldsearch = ctrl.search;
+        angular.forEach(items, function (item) {
+          var newItem = ctrl.tagging.fct ? ctrl.tagging.fct(item) : item;
+          if (newItem) {
+            ctrl.select(newItem, true);
+          }
+        });
+        ctrl.search = oldsearch || EMPTY_SEARCH;
+        e.preventDefault();
+        e.stopPropagation();
+      } else if (ctrl.paste) {
+        ctrl.paste(data);
+        ctrl.search = EMPTY_SEARCH;
+        e.preventDefault();
+        e.stopPropagation();
+      }
+    }
+  });
+
+  ctrl.searchInput.on('tagged', function() {
+    $timeout(function() {
+      _resetSearchInput();
+    });
+  });
+
+  // See https://github.com/ivaynberg/select2/blob/3.4.6/select2.js#L1431
+  function _ensureHighlightVisible() {
+    var container = $element.querySelectorAll('.ui-select-choices-content');
+    var choices = container.querySelectorAll('.ui-select-choices-row');
+    if (choices.length < 1) {
+      throw uiSelectMinErr('choices', "Expected multiple .ui-select-choices-row but got '{0}'.", choices.length);
+    }
+
+    if (ctrl.activeIndex < 0) {
+      return;
+    }
+
+    var highlighted = choices[ctrl.activeIndex];
+    var posY = highlighted.offsetTop + highlighted.clientHeight - container[0].scrollTop;
+    var height = container[0].offsetHeight;
+
+    if (posY > height) {
+      container[0].scrollTop += posY - height;
+    } else if (posY < highlighted.clientHeight) {
+      if (ctrl.isGrouped && ctrl.activeIndex === 0)
+        container[0].scrollTop = 0; //To make group header visible when going all the way up
+      else
+        container[0].scrollTop -= highlighted.clientHeight - posY;
+    }
+  }
+
+  var onResize = $$uisDebounce(function() {
+    ctrl.sizeSearchInput();
+  }, 50);
+
+  angular.element($window).bind('resize', onResize);
+
+  $scope.$on('$destroy', function() {
+    ctrl.searchInput.off('keyup keydown tagged blur paste');
+    angular.element($window).off('resize', onResize);
+  });
+
+  $scope.$watch('$select.activeIndex', function(activeIndex) {
+    if (activeIndex)
+      $element.find('input').attr(
+        'aria-activedescendant',
+        'ui-select-choices-row-' + ctrl.generatedId + '-' + activeIndex);
+  });
+
+  $scope.$watch('$select.open', function(open) {
+    if (!open)
+      $element.find('input').removeAttr('aria-activedescendant');
+  });
+}]);
+
+uis.directive('uiSelect',
+  ['$document', 'uiSelectConfig', 'uiSelectMinErr', 'uisOffset', '$compile', '$parse', '$timeout',
+  function($document, uiSelectConfig, uiSelectMinErr, uisOffset, $compile, $parse, $timeout) {
+
+  return {
+    restrict: 'EA',
+    templateUrl: function(tElement, tAttrs) {
+      var theme = tAttrs.theme || uiSelectConfig.theme;
+      return theme + (angular.isDefined(tAttrs.multiple) ? '/select-multiple.tpl.html' : '/select.tpl.html');
+    },
+    replace: true,
+    transclude: true,
+    require: ['uiSelect', '^ngModel'],
+    scope: true,
+
+    controller: 'uiSelectCtrl',
+    controllerAs: '$select',
+    compile: function(tElement, tAttrs) {
+
+      // Allow setting ngClass on uiSelect
+      var match = /{(.*)}\s*{(.*)}/.exec(tAttrs.ngClass);
+      if(match) {
+        var combined = '{'+ match[1] +', '+ match[2] +'}';
+        tAttrs.ngClass = combined;
+        tElement.attr('ng-class', combined);
+      }
+
+      //Multiple or Single depending if multiple attribute presence
+      if (angular.isDefined(tAttrs.multiple))
+        tElement.append('<ui-select-multiple/>').removeAttr('multiple');
+      else
+        tElement.append('<ui-select-single/>');
+
+      if (tAttrs.inputId)
+        tElement.querySelectorAll('input.ui-select-search')[0].id = tAttrs.inputId;
+
+      return function(scope, element, attrs, ctrls, transcludeFn) {
+
+        var $select = ctrls[0];
+        var ngModel = ctrls[1];
+
+        $select.generatedId = uiSelectConfig.generateId();
+        $select.baseTitle = attrs.title || 'Select box';
+        $select.focusserTitle = $select.baseTitle + ' focus';
+        $select.focusserId = 'focusser-' + $select.generatedId;
+
+        $select.closeOnSelect = function() {
+          if (angular.isDefined(attrs.closeOnSelect)) {
+            return $parse(attrs.closeOnSelect)();
+          } else {
+            return uiSelectConfig.closeOnSelect;
+          }
+        }();
+
+        scope.$watch('skipFocusser', function() {
+            var skipFocusser = scope.$eval(attrs.skipFocusser);
+            $select.skipFocusser = skipFocusser !== undefined ? skipFocusser : uiSelectConfig.skipFocusser;
+        });
+
+        $select.onSelectCallback = $parse(attrs.onSelect);
+        $select.onRemoveCallback = $parse(attrs.onRemove);
+
+        //Set reference to ngModel from uiSelectCtrl
+        $select.ngModel = ngModel;
+
+        $select.choiceGrouped = function(group){
+          return $select.isGrouped && group && group.name;
+        };
+
+        if(attrs.tabindex){
+          attrs.$observe('tabindex', function(value) {
+            $select.focusInput.attr('tabindex', value);
+            element.removeAttr('tabindex');
+          });
+        }
+
+        scope.$watch(function () { return scope.$eval(attrs.searchEnabled); }, function(newVal) {
+          $select.searchEnabled = newVal !== undefined ? newVal : uiSelectConfig.searchEnabled;
+        });
+
+        scope.$watch('sortable', function() {
+            var sortable = scope.$eval(attrs.sortable);
+            $select.sortable = sortable !== undefined ? sortable : uiSelectConfig.sortable;
+        });
+
+        attrs.$observe('backspaceReset', function() {
+          // $eval() is needed otherwise we get a string instead of a boolean
+          var backspaceReset = scope.$eval(attrs.backspaceReset);
+          $select.backspaceReset = backspaceReset !== undefined ? backspaceReset : true;
+        });
+
+        attrs.$observe('limit', function() {
+          //Limit the number of selections allowed
+          $select.limit = (angular.isDefined(attrs.limit)) ? parseInt(attrs.limit, 10) : undefined;
+        });
+
+        scope.$watch('removeSelected', function() {
+            var removeSelected = scope.$eval(attrs.removeSelected);
+            $select.removeSelected = removeSelected !== undefined ? removeSelected : uiSelectConfig.removeSelected;
+        });
+
+        attrs.$observe('disabled', function() {
+          // No need to use $eval() (thanks to ng-disabled) since we already get a boolean instead of a string
+          $select.disabled = attrs.disabled !== undefined ? attrs.disabled : false;
+        });
+
+        attrs.$observe('resetSearchInput', function() {
+          // $eval() is needed otherwise we get a string instead of a boolean
+          var resetSearchInput = scope.$eval(attrs.resetSearchInput);
+          $select.resetSearchInput = resetSearchInput !== undefined ? resetSearchInput : true;
+        });
+
+        attrs.$observe('paste', function() {
+          $select.paste = scope.$eval(attrs.paste);
+        });
+
+        attrs.$observe('tagging', function() {
+          if(attrs.tagging !== undefined)
+          {
+            // $eval() is needed otherwise we get a string instead of a boolean
+            var taggingEval = scope.$eval(attrs.tagging);
+            $select.tagging = {isActivated: true, fct: taggingEval !== true ? taggingEval : undefined};
+          }
+          else
+          {
+            $select.tagging = {isActivated: false, fct: undefined};
+          }
+        });
+
+        attrs.$observe('taggingLabel', function() {
+          if(attrs.tagging !== undefined )
+          {
+            // check eval for FALSE, in this case, we disable the labels
+            // associated with tagging
+            if ( attrs.taggingLabel === 'false' ) {
+              $select.taggingLabel = false;
+            }
+            else
+            {
+              $select.taggingLabel = attrs.taggingLabel !== undefined ? attrs.taggingLabel : '(new)';
+            }
+          }
+        });
+
+        attrs.$observe('taggingTokens', function() {
+          if (attrs.tagging !== undefined) {
+            var tokens = attrs.taggingTokens !== undefined ? attrs.taggingTokens.split('|') : [',','ENTER'];
+            $select.taggingTokens = {isActivated: true, tokens: tokens };
+          }
+        });
+
+        attrs.$observe('spinnerEnabled', function() {
+          // $eval() is needed otherwise we get a string instead of a boolean
+          var spinnerEnabled = scope.$eval(attrs.spinnerEnabled);
+          $select.spinnerEnabled = spinnerEnabled !== undefined ? spinnerEnabled : uiSelectConfig.spinnerEnabled;
+        });
+
+        attrs.$observe('spinnerClass', function() {
+          var spinnerClass = attrs.spinnerClass;
+          $select.spinnerClass = spinnerClass !== undefined ? attrs.spinnerClass : uiSelectConfig.spinnerClass;
+        });
+
+        //Automatically gets focus when loaded
+        if (angular.isDefined(attrs.autofocus)){
+          $timeout(function(){
+            $select.setFocus();
+          });
+        }
+
+        //Gets focus based on scope event name (e.g. focus-on='SomeEventName')
+        if (angular.isDefined(attrs.focusOn)){
+          scope.$on(attrs.focusOn, function() {
+              $timeout(function(){
+                $select.setFocus();
+              });
+          });
+        }
+
+        function onDocumentClick(e) {
+          if (!$select.open) return; //Skip it if dropdown is close
+
+          var contains = false;
+
+          if (window.jQuery) {
+            // Firefox 3.6 does not support element.contains()
+            // See Node.contains https://developer.mozilla.org/en-US/docs/Web/API/Node.contains
+            contains = window.jQuery.contains(element[0], e.target);
+          } else {
+            contains = element[0].contains(e.target);
+          }
+
+          if (!contains && !$select.clickTriggeredSelect) {
+            var skipFocusser;
+            if (!$select.skipFocusser) {
+              //Will lose focus only with certain targets
+              var focusableControls = ['input','button','textarea','select'];
+              var targetController = angular.element(e.target).controller('uiSelect'); //To check if target is other ui-select
+              skipFocusser = targetController && targetController !== $select; //To check if target is other ui-select
+              if (!skipFocusser) skipFocusser =  ~focusableControls.indexOf(e.target.tagName.toLowerCase()); //Check if target is input, button or textarea
+            } else {
+              skipFocusser = true;
+            }
+            $select.close(skipFocusser);
+            scope.$digest();
+          }
+          $select.clickTriggeredSelect = false;
+        }
+
+        // See Click everywhere but here event http://stackoverflow.com/questions/12931369
+        $document.on('click', onDocumentClick);
+
+        scope.$on('$destroy', function() {
+          $document.off('click', onDocumentClick);
+        });
+
+        // Move transcluded elements to their correct position in main template
+        transcludeFn(scope, function(clone) {
+          // See Transclude in AngularJS http://blog.omkarpatil.com/2012/11/transclude-in-angularjs.html
+
+          // One day jqLite will be replaced by jQuery and we will be able to write:
+          // var transcludedElement = clone.filter('.my-class')
+          // instead of creating a hackish DOM element:
+          var transcluded = angular.element('<div>').append(clone);
+
+          var transcludedMatch = transcluded.querySelectorAll('.ui-select-match');
+          transcludedMatch.removeAttr('ui-select-match'); //To avoid loop in case directive as attr
+          transcludedMatch.removeAttr('data-ui-select-match'); // Properly handle HTML5 data-attributes
+          if (transcludedMatch.length !== 1) {
+            throw uiSelectMinErr('transcluded', "Expected 1 .ui-select-match but got '{0}'.", transcludedMatch.length);
+          }
+          element.querySelectorAll('.ui-select-match').replaceWith(transcludedMatch);
+
+          var transcludedChoices = transcluded.querySelectorAll('.ui-select-choices');
+          transcludedChoices.removeAttr('ui-select-choices'); //To avoid loop in case directive as attr
+          transcludedChoices.removeAttr('data-ui-select-choices'); // Properly handle HTML5 data-attributes
+          if (transcludedChoices.length !== 1) {
+            throw uiSelectMinErr('transcluded', "Expected 1 .ui-select-choices but got '{0}'.", transcludedChoices.length);
+          }
+          element.querySelectorAll('.ui-select-choices').replaceWith(transcludedChoices);
+
+          var transcludedNoChoice = transcluded.querySelectorAll('.ui-select-no-choice');
+          transcludedNoChoice.removeAttr('ui-select-no-choice'); //To avoid loop in case directive as attr
+          transcludedNoChoice.removeAttr('data-ui-select-no-choice'); // Properly handle HTML5 data-attributes
+          if (transcludedNoChoice.length == 1) {
+            element.querySelectorAll('.ui-select-no-choice').replaceWith(transcludedNoChoice);
+          }
+        });
+
+        // Support for appending the select field to the body when its open
+        var appendToBody = scope.$eval(attrs.appendToBody);
+        if (appendToBody !== undefined ? appendToBody : uiSelectConfig.appendToBody) {
+          scope.$watch('$select.open', function(isOpen) {
+            if (isOpen) {
+              positionDropdown();
+            } else {
+              resetDropdown();
+            }
+          });
+
+          // Move the dropdown back to its original location when the scope is destroyed. Otherwise
+          // it might stick around when the user routes away or the select field is otherwise removed
+          scope.$on('$destroy', function() {
+            resetDropdown();
+          });
+        }
+
+        // Hold on to a reference to the .ui-select-container element for appendToBody support
+        var placeholder = null,
+            originalWidth = '';
+
+        function positionDropdown() {
+          // Remember the absolute position of the element
+          var offset = uisOffset(element);
+
+          // Clone the element into a placeholder element to take its original place in the DOM
+          placeholder = angular.element('<div class="ui-select-placeholder"></div>');
+          placeholder[0].style.width = offset.width + 'px';
+          placeholder[0].style.height = offset.height + 'px';
+          element.after(placeholder);
+
+          // Remember the original value of the element width inline style, so it can be restored
+          // when the dropdown is closed
+          originalWidth = element[0].style.width;
+
+          // Now move the actual dropdown element to the end of the body
+          $document.find('body').append(element);
+
+          element[0].style.position = 'absolute';
+          element[0].style.left = offset.left + 'px';
+          element[0].style.top = offset.top + 'px';
+          element[0].style.width = offset.width + 'px';
+        }
+
+        function resetDropdown() {
+          if (placeholder === null) {
+            // The dropdown has not actually been display yet, so there's nothing to reset
+            return;
+          }
+
+          // Move the dropdown element back to its original location in the DOM
+          placeholder.replaceWith(element);
+          placeholder = null;
+
+          element[0].style.position = '';
+          element[0].style.left = '';
+          element[0].style.top = '';
+          element[0].style.width = originalWidth;
+
+          // Set focus back on to the moved element
+          $select.setFocus();
+        }
+
+        // Hold on to a reference to the .ui-select-dropdown element for direction support.
+        var dropdown = null,
+            directionUpClassName = 'direction-up';
+
+        // Support changing the direction of the dropdown if there isn't enough space to render it.
+        scope.$watch('$select.open', function() {
+
+          if ($select.dropdownPosition === 'auto' || $select.dropdownPosition === 'up'){
+            scope.calculateDropdownPos();
+          }
+
+        });
+
+        var setDropdownPosUp = function(offset, offsetDropdown){
+
+          offset = offset || uisOffset(element);
+          offsetDropdown = offsetDropdown || uisOffset(dropdown);
+
+          dropdown[0].style.position = 'absolute';
+          dropdown[0].style.top = (offsetDropdown.height * -1) + 'px';
+          element.addClass(directionUpClassName);
+
+        };
+
+        var setDropdownPosDown = function(offset, offsetDropdown){
+
+          element.removeClass(directionUpClassName);
+
+          offset = offset || uisOffset(element);
+          offsetDropdown = offsetDropdown || uisOffset(dropdown);
+
+          dropdown[0].style.position = '';
+          dropdown[0].style.top = '';
+
+        };
+
+        var calculateDropdownPosAfterAnimation = function() {
+          // Delay positioning the dropdown until all choices have been added so its height is correct.
+          $timeout(function() {
+            if ($select.dropdownPosition === 'up') {
+              //Go UP
+              setDropdownPosUp();
+            } else {
+              //AUTO
+              element.removeClass(directionUpClassName);
+
+              var offset = uisOffset(element);
+              var offsetDropdown = uisOffset(dropdown);
+
+              //https://code.google.com/p/chromium/issues/detail?id=342307#c4
+              var scrollTop = $document[0].documentElement.scrollTop || $document[0].body.scrollTop; //To make it cross browser (blink, webkit, IE, Firefox).
+
+              // Determine if the direction of the dropdown needs to be changed.
+              if (offset.top + offset.height + offsetDropdown.height > scrollTop + $document[0].documentElement.clientHeight) {
+                //Go UP
+                setDropdownPosUp(offset, offsetDropdown);
+              }else{
+                //Go DOWN
+                setDropdownPosDown(offset, offsetDropdown);
+              }
+            }
+
+            // Display the dropdown once it has been positioned.
+            dropdown[0].style.opacity = 1;
+          });
+        };
+
+        var opened = false;
+        
+        scope.calculateDropdownPos = function() {
+          if ($select.open) {
+            dropdown = angular.element(element).querySelectorAll('.ui-select-dropdown');
+
+            if (dropdown.length === 0) {
+              return;
+            }
+
+           // Hide the dropdown so there is no flicker until $timeout is done executing.
+           if ($select.search === '' && !opened) {
+              dropdown[0].style.opacity = 0;
+              opened = true;
+           }
+
+            if (!uisOffset(dropdown).height && $select.$animate && $select.$animate.on && $select.$animate.enabled(dropdown)) {
+              var needsCalculated = true;
+
+              $select.$animate.on('enter', dropdown, function (elem, phase) {
+                if (phase === 'close' && needsCalculated) {
+                  calculateDropdownPosAfterAnimation();
+                  needsCalculated = false;
+                }
+              });
+            } else {
+              calculateDropdownPosAfterAnimation();
+            }
+          } else {
+            if (dropdown === null || dropdown.length === 0) {
+              return;
+            }
+
+            // Reset the position of the dropdown.
+            dropdown[0].style.opacity = 0;
+            dropdown[0].style.position = '';
+            dropdown[0].style.top = '';
+            element.removeClass(directionUpClassName);
+          }
+        };
+      };
+    }
+  };
+}]);
+
+uis.directive('uiSelectMatch', ['uiSelectConfig', function(uiSelectConfig) {
+  return {
+    restrict: 'EA',
+    require: '^uiSelect',
+    replace: true,
+    transclude: true,
+    templateUrl: function(tElement) {
+      // Needed so the uiSelect can detect the transcluded content
+      tElement.addClass('ui-select-match');
+
+      var parent = tElement.parent();
+      // Gets theme attribute from parent (ui-select)
+      var theme = getAttribute(parent, 'theme') || uiSelectConfig.theme;
+      var multi = angular.isDefined(getAttribute(parent, 'multiple'));
+
+      return theme + (multi ? '/match-multiple.tpl.html' : '/match.tpl.html');      
+    },
+    link: function(scope, element, attrs, $select) {
+      $select.lockChoiceExpression = attrs.uiLockChoice;
+      attrs.$observe('placeholder', function(placeholder) {
+        $select.placeholder = placeholder !== undefined ? placeholder : uiSelectConfig.placeholder;
+      });
+
+      function setAllowClear(allow) {
+        $select.allowClear = (angular.isDefined(allow)) ? (allow === '') ? true : (allow.toLowerCase() === 'true') : false;
+      }
+
+      attrs.$observe('allowClear', setAllowClear);
+      setAllowClear(attrs.allowClear);
+
+      if($select.multiple){
+        $select.sizeSearchInput();
+      }
+
+    }
+  };
+
+  function getAttribute(elem, attribute) {
+    if (elem[0].hasAttribute(attribute))
+      return elem.attr(attribute);
+
+    if (elem[0].hasAttribute('data-' + attribute))
+      return elem.attr('data-' + attribute);
+
+    if (elem[0].hasAttribute('x-' + attribute))
+      return elem.attr('x-' + attribute);
+  }
+}]);
+
+uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelectMinErr, $timeout) {
+  return {
+    restrict: 'EA',
+    require: ['^uiSelect', '^ngModel'],
+
+    controller: ['$scope','$timeout', function($scope, $timeout){
+
+      var ctrl = this,
+          $select = $scope.$select,
+          ngModel;
+
+      if (angular.isUndefined($select.selected))
+        $select.selected = [];
+
+      //Wait for link fn to inject it
+      $scope.$evalAsync(function(){ ngModel = $scope.ngModel; });
+
+      ctrl.activeMatchIndex = -1;
+
+      ctrl.updateModel = function(){
+        ngModel.$setViewValue(Date.now()); //Set timestamp as a unique string to force changes
+        ctrl.refreshComponent();
+      };
+
+      ctrl.refreshComponent = function(){
+        //Remove already selected items
+        //e.g. When user clicks on a selection, the selected array changes and
+        //the dropdown should remove that item
+        if($select.refreshItems){
+          $select.refreshItems();
+        }
+        if($select.sizeSearchInput){
+          $select.sizeSearchInput();
+        }
+      };
+
+      // Remove item from multiple select
+      ctrl.removeChoice = function(index){
+
+        // if the choice is locked, don't remove it
+        if($select.isLocked(null, index)) return false;
+
+        var removedChoice = $select.selected[index];
+
+        var locals = {};
+        locals[$select.parserResult.itemName] = removedChoice;
+
+        $select.selected.splice(index, 1);
+        ctrl.activeMatchIndex = -1;
+        $select.sizeSearchInput();
+
+        // Give some time for scope propagation.
+        $timeout(function(){
+          $select.onRemoveCallback($scope, {
+            $item: removedChoice,
+            $model: $select.parserResult.modelMapper($scope, locals)
+          });
+        });
+
+        ctrl.updateModel();
+
+        return true;
+      };
+
+      ctrl.getPlaceholder = function(){
+        //Refactor single?
+        if($select.selected && $select.selected.length) return;
+        return $select.placeholder;
+      };
+
+
+    }],
+    controllerAs: '$selectMultiple',
+
+    link: function(scope, element, attrs, ctrls) {
+
+      var $select = ctrls[0];
+      var ngModel = scope.ngModel = ctrls[1];
+      var $selectMultiple = scope.$selectMultiple;
+
+      //$select.selected = raw selected objects (ignoring any property binding)
+
+      $select.multiple = true;
+
+      //Input that will handle focus
+      $select.focusInput = $select.searchInput;
+
+      //Properly check for empty if set to multiple
+      ngModel.$isEmpty = function(value) {
+        return !value || value.length === 0;
+      };
+
+      //From view --> model
+      ngModel.$parsers.unshift(function () {
+        var locals = {},
+            result,
+            resultMultiple = [];
+        for (var j = $select.selected.length - 1; j >= 0; j--) {
+          locals = {};
+          locals[$select.parserResult.itemName] = $select.selected[j];
+          result = $select.parserResult.modelMapper(scope, locals);
+          resultMultiple.unshift(result);
+        }
+        return resultMultiple;
+      });
+
+      // From model --> view
+      ngModel.$formatters.unshift(function (inputValue) {
+        var data = $select.parserResult && $select.parserResult.source (scope, { $select : {search:''}}), //Overwrite $search
+            locals = {},
+            result;
+        if (!data) return inputValue;
+        var resultMultiple = [];
+        var checkFnMultiple = function(list, value){
+          if (!list || !list.length) return;
+          for (var p = list.length - 1; p >= 0; p--) {
+            locals[$select.parserResult.itemName] = list[p];
+            result = $select.parserResult.modelMapper(scope, locals);
+            if($select.parserResult.trackByExp){
+                var propsItemNameMatches = /(\w*)\./.exec($select.parserResult.trackByExp);
+                var matches = /\.([^\s]+)/.exec($select.parserResult.trackByExp);
+                if(propsItemNameMatches && propsItemNameMatches.length > 0 && propsItemNameMatches[1] == $select.parserResult.itemName){
+                  if(matches && matches.length>0 && result[matches[1]] == value[matches[1]]){
+                      resultMultiple.unshift(list[p]);
+                      return true;
+                  }
+                }
+            }
+            if (angular.equals(result,value)){
+              resultMultiple.unshift(list[p]);
+              return true;
+            }
+          }
+          return false;
+        };
+        if (!inputValue) return resultMultiple; //If ngModel was undefined
+        for (var k = inputValue.length - 1; k >= 0; k--) {
+          //Check model array of currently selected items
+          if (!checkFnMultiple($select.selected, inputValue[k])){
+            //Check model array of all items available
+            if (!checkFnMultiple(data, inputValue[k])){
+              //If not found on previous lists, just add it directly to resultMultiple
+              resultMultiple.unshift(inputValue[k]);
+            }
+          }
+        }
+        return resultMultiple;
+      });
+
+      //Watch for external model changes
+      scope.$watchCollection(function(){ return ngModel.$modelValue; }, function(newValue, oldValue) {
+        if (oldValue != newValue){
+          //update the view value with fresh data from items, if there is a valid model value
+          if(angular.isDefined(ngModel.$modelValue)) {
+            ngModel.$modelValue = null; //Force scope model value and ngModel value to be out of sync to re-run formatters
+          }
+          $selectMultiple.refreshComponent();
+        }
+      });
+
+      ngModel.$render = function() {
+        // Make sure that model value is array
+        if(!angular.isArray(ngModel.$viewValue)){
+          // Have tolerance for null or undefined values
+          if (isNil(ngModel.$viewValue)){
+            ngModel.$viewValue = [];
+          } else {
+            throw uiSelectMinErr('multiarr', "Expected model value to be array but got '{0}'", ngModel.$viewValue);
+          }
+        }
+        $select.selected = ngModel.$viewValue;
+        $selectMultiple.refreshComponent();
+        scope.$evalAsync(); //To force $digest
+      };
+
+      scope.$on('uis:select', function (event, item) {
+        if($select.selected.length >= $select.limit) {
+          return;
+        }
+        $select.selected.push(item);
+        var locals = {};
+        locals[$select.parserResult.itemName] = item;
+
+        $timeout(function(){
+          $select.onSelectCallback(scope, {
+            $item: item,
+            $model: $select.parserResult.modelMapper(scope, locals)
+          });
+        });
+        $selectMultiple.updateModel();
+      });
+
+      scope.$on('uis:activate', function () {
+        $selectMultiple.activeMatchIndex = -1;
+      });
+
+      scope.$watch('$select.disabled', function(newValue, oldValue) {
+        // As the search input field may now become visible, it may be necessary to recompute its size
+        if (oldValue && !newValue) $select.sizeSearchInput();
+      });
+
+      $select.searchInput.on('keydown', function(e) {
+        var key = e.which;
+        scope.$apply(function() {
+          var processed = false;
+          // var tagged = false; //Checkme
+          if(KEY.isHorizontalMovement(key)){
+            processed = _handleMatchSelection(key);
+          }
+          if (processed  && key != KEY.TAB) {
+            //TODO Check si el tab selecciona aun correctamente
+            //Crear test
+            e.preventDefault();
+            e.stopPropagation();
+          }
+        });
+      });
+      function _getCaretPosition(el) {
+        if(angular.isNumber(el.selectionStart)) return el.selectionStart;
+        // selectionStart is not supported in IE8 and we don't want hacky workarounds so we compromise
+        else return el.value.length;
+      }
+      // Handles selected options in "multiple" mode
+      function _handleMatchSelection(key){
+        var caretPosition = _getCaretPosition($select.searchInput[0]),
+            length = $select.selected.length,
+            // none  = -1,
+            first = 0,
+            last  = length-1,
+            curr  = $selectMultiple.activeMatchIndex,
+            next  = $selectMultiple.activeMatchIndex+1,
+            prev  = $selectMultiple.activeMatchIndex-1,
+            newIndex = curr;
+
+        if(caretPosition > 0 || ($select.search.length && key == KEY.RIGHT)) return false;
+
+        $select.close();
+
+        function getNewActiveMatchIndex(){
+          switch(key){
+            case KEY.LEFT:
+              // Select previous/first item
+              if(~$selectMultiple.activeMatchIndex) return prev;
+              // Select last item
+              else return last;
+              break;
+            case KEY.RIGHT:
+              // Open drop-down
+              if(!~$selectMultiple.activeMatchIndex || curr === last){
+                $select.activate();
+                return false;
+              }
+              // Select next/last item
+              else return next;
+              break;
+            case KEY.BACKSPACE:
+              // Remove selected item and select previous/first
+              if(~$selectMultiple.activeMatchIndex){
+                if($selectMultiple.removeChoice(curr)) {
+                  return prev;
+                } else {
+                  return curr;
+                }
+
+              } else {
+                // If nothing yet selected, select last item
+                return last;
+              }
+              break;
+            case KEY.DELETE:
+              // Remove selected item and select next item
+              if(~$selectMultiple.activeMatchIndex){
+                $selectMultiple.removeChoice($selectMultiple.activeMatchIndex);
+                return curr;
+              }
+              else return false;
+          }
+        }
+
+        newIndex = getNewActiveMatchIndex();
+
+        if(!$select.selected.length || newIndex === false) $selectMultiple.activeMatchIndex = -1;
+        else $selectMultiple.activeMatchIndex = Math.min(last,Math.max(first,newIndex));
+
+        return true;
+      }
+
+      $select.searchInput.on('keyup', function(e) {
+
+        if ( ! KEY.isVerticalMovement(e.which) ) {
+          scope.$evalAsync( function () {
+            $select.activeIndex = $select.taggingLabel === false ? -1 : 0;
+          });
+        }
+        // Push a "create new" item into array if there is a search string
+        if ( $select.tagging.isActivated && $select.search.length > 0 ) {
+
+          // return early with these keys
+          if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC || KEY.isVerticalMovement(e.which) ) {
+            return;
+          }
+          // always reset the activeIndex to the first item when tagging
+          $select.activeIndex = $select.taggingLabel === false ? -1 : 0;
+          // taggingLabel === false bypasses all of this
+          if ($select.taggingLabel === false) return;
+
+          var items = angular.copy( $select.items );
+          var stashArr = angular.copy( $select.items );
+          var newItem;
+          var item;
+          var hasTag = false;
+          var dupeIndex = -1;
+          var tagItems;
+          var tagItem;
+
+          // case for object tagging via transform `$select.tagging.fct` function
+          if ( $select.tagging.fct !== undefined) {
+            tagItems = $select.$filter('filter')(items,{'isTag': true});
+            if ( tagItems.length > 0 ) {
+              tagItem = tagItems[0];
+            }
+            // remove the first element, if it has the `isTag` prop we generate a new one with each keyup, shaving the previous
+            if ( items.length > 0 && tagItem ) {
+              hasTag = true;
+              items = items.slice(1,items.length);
+              stashArr = stashArr.slice(1,stashArr.length);
+            }
+            newItem = $select.tagging.fct($select.search);
+            // verify the new tag doesn't match the value of a possible selection choice or an already selected item.
+            if (
+              stashArr.some(function (origItem) {
+                 return angular.equals(origItem, newItem);
+              }) ||
+              $select.selected.some(function (origItem) {
+                return angular.equals(origItem, newItem);
+              })
+            ) {
+              scope.$evalAsync(function () {
+                $select.activeIndex = 0;
+                $select.items = items;
+              });
+              return;
+            }
+            if (newItem) newItem.isTag = true;
+          // handle newItem string and stripping dupes in tagging string context
+          } else {
+            // find any tagging items already in the $select.items array and store them
+            tagItems = $select.$filter('filter')(items,function (item) {
+              return item.match($select.taggingLabel);
+            });
+            if ( tagItems.length > 0 ) {
+              tagItem = tagItems[0];
+            }
+            item = items[0];
+            // remove existing tag item if found (should only ever be one tag item)
+            if ( item !== undefined && items.length > 0 && tagItem ) {
+              hasTag = true;
+              items = items.slice(1,items.length);
+              stashArr = stashArr.slice(1,stashArr.length);
+            }
+            newItem = $select.search+' '+$select.taggingLabel;
+            if ( _findApproxDupe($select.selected, $select.search) > -1 ) {
+              return;
+            }
+            // verify the the tag doesn't match the value of an existing item from
+            // the searched data set or the items already selected
+            if ( _findCaseInsensitiveDupe(stashArr.concat($select.selected)) ) {
+              // if there is a tag from prev iteration, strip it / queue the change
+              // and return early
+              if ( hasTag ) {
+                items = stashArr;
+                scope.$evalAsync( function () {
+                  $select.activeIndex = 0;
+                  $select.items = items;
+                });
+              }
+              return;
+            }
+            if ( _findCaseInsensitiveDupe(stashArr) ) {
+              // if there is a tag from prev iteration, strip it
+              if ( hasTag ) {
+                $select.items = stashArr.slice(1,stashArr.length);
+              }
+              return;
+            }
+          }
+          if ( hasTag ) dupeIndex = _findApproxDupe($select.selected, newItem);
+          // dupe found, shave the first item
+          if ( dupeIndex > -1 ) {
+            items = items.slice(dupeIndex+1,items.length-1);
+          } else {
+            items = [];
+            if (newItem) items.push(newItem);
+            items = items.concat(stashArr);
+          }
+          scope.$evalAsync( function () {
+            $select.activeIndex = 0;
+            $select.items = items;
+
+            if ($select.isGrouped) {
+              // update item references in groups, so that indexOf will work after angular.copy
+              var itemsWithoutTag = newItem ? items.slice(1) : items;
+              $select.setItemsFn(itemsWithoutTag);
+              if (newItem) {
+                // add tag item as a new group
+                $select.items.unshift(newItem);
+                $select.groups.unshift({name: '', items: [newItem], tagging: true});
+              }
+            }
+          });
+        }
+      });
+      function _findCaseInsensitiveDupe(arr) {
+        if ( arr === undefined || $select.search === undefined ) {
+          return false;
+        }
+        var hasDupe = arr.filter( function (origItem) {
+          if ( $select.search.toUpperCase() === undefined || origItem === undefined ) {
+            return false;
+          }
+          return origItem.toUpperCase() === $select.search.toUpperCase();
+        }).length > 0;
+
+        return hasDupe;
+      }
+      function _findApproxDupe(haystack, needle) {
+        var dupeIndex = -1;
+        if(angular.isArray(haystack)) {
+          var tempArr = angular.copy(haystack);
+          for (var i = 0; i <tempArr.length; i++) {
+            // handle the simple string version of tagging
+            if ( $select.tagging.fct === undefined ) {
+              // search the array for the match
+              if ( tempArr[i]+' '+$select.taggingLabel === needle ) {
+              dupeIndex = i;
+              }
+            // handle the object tagging implementation
+            } else {
+              var mockObj = tempArr[i];
+              if (angular.isObject(mockObj)) {
+                mockObj.isTag = true;
+              }
+              if ( angular.equals(mockObj, needle) ) {
+                dupeIndex = i;
+              }
+            }
+          }
+        }
+        return dupeIndex;
+      }
+
+      $select.searchInput.on('blur', function() {
+        $timeout(function() {
+          $selectMultiple.activeMatchIndex = -1;
+        });
+      });
+
+    }
+  };
+}]);
+
+uis.directive('uiSelectNoChoice',
+    ['uiSelectConfig', function (uiSelectConfig) {
+        return {
+            restrict: 'EA',
+            require: '^uiSelect',
+            replace: true,
+            transclude: true,
+            templateUrl: function (tElement) {
+                // Needed so the uiSelect can detect the transcluded content
+                tElement.addClass('ui-select-no-choice');
+      
+                // Gets theme attribute from parent (ui-select)
+                var theme = tElement.parent().attr('theme') || uiSelectConfig.theme;
+                return theme + '/no-choice.tpl.html';
+            }
+        };
+    }]);
+
+uis.directive('uiSelectSingle', ['$timeout','$compile', function($timeout, $compile) {
+  return {
+    restrict: 'EA',
+    require: ['^uiSelect', '^ngModel'],
+    link: function(scope, element, attrs, ctrls) {
+
+      var $select = ctrls[0];
+      var ngModel = ctrls[1];
+
+      //From view --> model
+      ngModel.$parsers.unshift(function (inputValue) {
+        // Keep original value for undefined and null
+        if (isNil(inputValue)) {
+          return inputValue;
+        }
+
+        var locals = {},
+            result;
+        locals[$select.parserResult.itemName] = inputValue;
+        result = $select.parserResult.modelMapper(scope, locals);
+        return result;
+      });
+
+      //From model --> view
+      ngModel.$formatters.unshift(function (inputValue) {
+        // Keep original value for undefined and null
+        if (isNil(inputValue)) {
+          return inputValue;
+        }
+
+        var data = $select.parserResult && $select.parserResult.source (scope, { $select : {search:''}}), //Overwrite $search
+            locals = {},
+            result;
+        if (data){
+          var checkFnSingle = function(d){
+            locals[$select.parserResult.itemName] = d;
+            result = $select.parserResult.modelMapper(scope, locals);
+            return result === inputValue;
+          };
+          //If possible pass same object stored in $select.selected
+          if ($select.selected && checkFnSingle($select.selected)) {
+            return $select.selected;
+          }
+          for (var i = data.length - 1; i >= 0; i--) {
+            if (checkFnSingle(data[i])) return data[i];
+          }
+        }
+        return inputValue;
+      });
+
+      //Update viewValue if model change
+      scope.$watch('$select.selected', function(newValue) {
+        if (ngModel.$viewValue !== newValue) {
+          ngModel.$setViewValue(newValue);
+        }
+      });
+
+      ngModel.$render = function() {
+        $select.selected = ngModel.$viewValue;
+      };
+
+      scope.$on('uis:select', function (event, item) {
+        $select.selected = item;
+        var locals = {};
+        locals[$select.parserResult.itemName] = item;
+
+        $timeout(function() {
+          $select.onSelectCallback(scope, {
+            $item: item,
+            $model: isNil(item) ? item : $select.parserResult.modelMapper(scope, locals)
+          });
+        });
+      });
+
+      scope.$on('uis:close', function (event, skipFocusser) {
+        $timeout(function(){
+          $select.focusser.prop('disabled', false);
+          if (!skipFocusser) $select.focusser[0].focus();
+        },0,false);
+      });
+
+      scope.$on('uis:activate', function () {
+        focusser.prop('disabled', true); //Will reactivate it on .close()
+      });
+
+      //Idea from: https://github.com/ivaynberg/select2/blob/79b5bf6db918d7560bdd959109b7bcfb47edaf43/select2.js#L1954
+      var focusser = angular.element("<input ng-disabled='$select.disabled' class='ui-select-focusser ui-select-offscreen' type='text' id='{{ $select.focusserId }}' aria-label='{{ $select.focusserTitle }}' aria-haspopup='true' role='button' />");
+      $compile(focusser)(scope);
+      $select.focusser = focusser;
+
+      //Input that will handle focus
+      $select.focusInput = focusser;
+
+      element.parent().append(focusser);
+      focusser.bind("focus", function(){
+        scope.$evalAsync(function(){
+          $select.focus = true;
+        });
+      });
+      focusser.bind("blur", function(){
+        scope.$evalAsync(function(){
+          $select.focus = false;
+        });
+      });
+      focusser.bind("keydown", function(e){
+
+        if (e.which === KEY.BACKSPACE && $select.backspaceReset !== false) {
+          e.preventDefault();
+          e.stopPropagation();
+          $select.select(undefined);
+          scope.$apply();
+          return;
+        }
+
+        if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
+          return;
+        }
+
+        if (e.which == KEY.DOWN  || e.which == KEY.UP || e.which == KEY.ENTER || e.which == KEY.SPACE){
+          e.preventDefault();
+          e.stopPropagation();
+          $select.activate();
+        }
+
+        scope.$digest();
+      });
+
+      focusser.bind("keyup input", function(e){
+
+        if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC || e.which == KEY.ENTER || e.which === KEY.BACKSPACE) {
+          return;
+        }
+
+        $select.activate(focusser.val()); //User pressed some regular key, so we pass it to the search input
+        focusser.val('');
+        scope.$digest();
+
+      });
+
+
+    }
+  };
+}]);
+
+// Make multiple matches sortable
+uis.directive('uiSelectSort', ['$timeout', 'uiSelectConfig', 'uiSelectMinErr', function($timeout, uiSelectConfig, uiSelectMinErr) {
+  return {
+    require: ['^^uiSelect', '^ngModel'],
+    link: function(scope, element, attrs, ctrls) {
+      if (scope[attrs.uiSelectSort] === null) {
+        throw uiSelectMinErr('sort', 'Expected a list to sort');
+      }
+
+      var $select = ctrls[0];
+      var $ngModel = ctrls[1];
+
+      var options = angular.extend({
+          axis: 'horizontal'
+        },
+        scope.$eval(attrs.uiSelectSortOptions));
+
+      var axis = options.axis;
+      var draggingClassName = 'dragging';
+      var droppingClassName = 'dropping';
+      var droppingBeforeClassName = 'dropping-before';
+      var droppingAfterClassName = 'dropping-after';
+
+      scope.$watch(function(){
+        return $select.sortable;
+      }, function(newValue){
+        if (newValue) {
+          element.attr('draggable', true);
+        } else {
+          element.removeAttr('draggable');
+        }
+      });
+
+      element.on('dragstart', function(event) {
+        element.addClass(draggingClassName);
+
+        (event.dataTransfer || event.originalEvent.dataTransfer).setData('text', scope.$index.toString());
+      });
+
+      element.on('dragend', function() {
+        removeClass(draggingClassName);
+      });
+
+      var move = function(from, to) {
+        /*jshint validthis: true */
+        this.splice(to, 0, this.splice(from, 1)[0]);
+      };
+
+      var removeClass = function(className) {
+        angular.forEach($select.$element.querySelectorAll('.' + className), function(el){
+          angular.element(el).removeClass(className);
+        });
+      };
+
+      var dragOverHandler = function(event) {
+        event.preventDefault();
+
+        var offset = axis === 'vertical' ? event.offsetY || event.layerY || (event.originalEvent ? event.originalEvent.offsetY : 0) : event.offsetX || event.layerX || (event.originalEvent ? event.originalEvent.offsetX : 0);
+
+        if (offset < (this[axis === 'vertical' ? 'offsetHeight' : 'offsetWidth'] / 2)) {
+          removeClass(droppingAfterClassName);
+          element.addClass(droppingBeforeClassName);
+
+        } else {
+          removeClass(droppingBeforeClassName);
+          element.addClass(droppingAfterClassName);
+        }
+      };
+
+      var dropTimeout;
+
+      var dropHandler = function(event) {
+        event.preventDefault();
+
+        var droppedItemIndex = parseInt((event.dataTransfer || event.originalEvent.dataTransfer).getData('text'), 10);
+
+        // prevent event firing multiple times in firefox
+        $timeout.cancel(dropTimeout);
+        dropTimeout = $timeout(function() {
+          _dropHandler(droppedItemIndex);
+        }, 20);
+      };
+
+      var _dropHandler = function(droppedItemIndex) {
+        var theList = scope.$eval(attrs.uiSelectSort);
+        var itemToMove = theList[droppedItemIndex];
+        var newIndex = null;
+
+        if (element.hasClass(droppingBeforeClassName)) {
+          if (droppedItemIndex < scope.$index) {
+            newIndex = scope.$index - 1;
+          } else {
+            newIndex = scope.$index;
+          }
+        } else {
+          if (droppedItemIndex < scope.$index) {
+            newIndex = scope.$index;
+          } else {
+            newIndex = scope.$index + 1;
+          }
+        }
+
+        move.apply(theList, [droppedItemIndex, newIndex]);
+
+        $ngModel.$setViewValue(Date.now());
+
+        scope.$apply(function() {
+          scope.$emit('uiSelectSort:change', {
+            array: theList,
+            item: itemToMove,
+            from: droppedItemIndex,
+            to: newIndex
+          });
+        });
+
+        removeClass(droppingClassName);
+        removeClass(droppingBeforeClassName);
+        removeClass(droppingAfterClassName);
+
+        element.off('drop', dropHandler);
+      };
+
+      element.on('dragenter', function() {
+        if (element.hasClass(draggingClassName)) {
+          return;
+        }
+
+        element.addClass(droppingClassName);
+
+        element.on('dragover', dragOverHandler);
+        element.on('drop', dropHandler);
+      });
+
+      element.on('dragleave', function(event) {
+        if (event.target != element) {
+          return;
+        }
+
+        removeClass(droppingClassName);
+        removeClass(droppingBeforeClassName);
+        removeClass(droppingAfterClassName);
+
+        element.off('dragover', dragOverHandler);
+        element.off('drop', dropHandler);
+      });
+    }
+  };
+}]);
+
+uis.directive('uisOpenClose', ['$parse', '$timeout', function ($parse, $timeout) {
+  return {
+    restrict: 'A',
+    require: 'uiSelect',
+    link: function (scope, element, attrs, $select) {
+      $select.onOpenCloseCallback = $parse(attrs.uisOpenClose);
+
+      scope.$watch('$select.open', function (isOpen, previousState) {
+        if (isOpen !== previousState) {
+          $timeout(function () {
+            $select.onOpenCloseCallback(scope, {
+              isOpen: isOpen
+            });
+          });
+        }
+      });
+    }
+  };
+}]);
+
+/**
+ * Parses "repeat" attribute.
+ *
+ * Taken from AngularJS ngRepeat source code
+ * See https://github.com/angular/angular.js/blob/v1.2.15/src/ng/directive/ngRepeat.js#L211
+ *
+ * Original discussion about parsing "repeat" attribute instead of fully relying on ng-repeat:
+ * https://github.com/angular-ui/ui-select/commit/5dd63ad#commitcomment-5504697
+ */
+
+uis.service('uisRepeatParser', ['uiSelectMinErr','$parse', function(uiSelectMinErr, $parse) {
+  var self = this;
+
+  /**
+   * Example:
+   * expression = "address in addresses | filter: {street: $select.search} track by $index"
+   * itemName = "address",
+   * source = "addresses | filter: {street: $select.search}",
+   * trackByExp = "$index",
+   */
+  self.parse = function(expression) {
+
+
+    var match;
+    //var isObjectCollection = /\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)/.test(expression);
+    // If an array is used as collection
+
+    // if (isObjectCollection){
+    // 000000000000000000000000000000111111111000000000000000222222222222220033333333333333333333330000444444444444444444000000000000000055555555555000000000000000000000066666666600000000
+    match = expression.match(/^\s*(?:([\s\S]+?)\s+as\s+)?(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(\s*[\s\S]+?)?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
+
+    // 1 Alias
+    // 2 Item
+    // 3 Key on (key,value)
+    // 4 Value on (key,value)
+    // 5 Source expression (including filters)
+    // 6 Track by
+
+    if (!match) {
+      throw uiSelectMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
+              expression);
+    }
+    
+    var source = match[5], 
+        filters = '';
+
+    // When using (key,value) ui-select requires filters to be extracted, since the object
+    // is converted to an array for $select.items 
+    // (in which case the filters need to be reapplied)
+    if (match[3]) {
+      // Remove any enclosing parenthesis
+      source = match[5].replace(/(^\()|(\)$)/g, '');
+      // match all after | but not after ||
+      var filterMatch = match[5].match(/^\s*(?:[\s\S]+?)(?:[^\|]|\|\|)+([\s\S]*)\s*$/);
+      if(filterMatch && filterMatch[1].trim()) {
+        filters = filterMatch[1];
+        source = source.replace(filters, '');
+      }      
+    }
+
+    return {
+      itemName: match[4] || match[2], // (lhs) Left-hand side,
+      keyName: match[3], //for (key, value) syntax
+      source: $parse(source),
+      filters: filters,
+      trackByExp: match[6],
+      modelMapper: $parse(match[1] || match[4] || match[2]),
+      repeatExpression: function (grouped) {
+        var expression = this.itemName + ' in ' + (grouped ? '$group.items' : '$select.items');
+        if (this.trackByExp) {
+          expression += ' track by ' + this.trackByExp;
+        }
+        return expression;
+      } 
+    };
+
+  };
+
+  self.getGroupNgRepeatExpression = function() {
+    return '$group in $select.groups track by $group.name';
+  };
+
+}]);
+
+}());
+angular.module("ui.select").run(["$templateCache", function($templateCache) {$templateCache.put("bootstrap/choices.tpl.html","<ul class=\"ui-select-choices ui-select-choices-content ui-select-dropdown dropdown-menu\" ng-show=\"$select.open && $select.items.length > 0\"><li class=\"ui-select-choices-group\" id=\"ui-select-choices-{{ $select.generatedId }}\"><div class=\"divider\" ng-show=\"$select.isGrouped && $index > 0\"></div><div ng-show=\"$select.isGrouped\" class=\"ui-select-choices-group-label dropdown-header\" ng-bind=\"$group.name\"></div><div ng-attr-id=\"ui-select-choices-row-{{ $select.generatedId }}-{{$index}}\" class=\"ui-select-choices-row\" ng-class=\"{active: $select.isActive(this), disabled: $select.isDisabled(this)}\" role=\"option\"><span class=\"ui-select-choices-row-inner\"></span></div></li></ul>");
+$templateCache.put("bootstrap/match-multiple.tpl.html","<span class=\"ui-select-match\"><span ng-repeat=\"$item in $select.selected track by $index\"><span class=\"ui-select-match-item btn btn-default btn-xs\" tabindex=\"-1\" type=\"button\" ng-disabled=\"$select.disabled\" ng-click=\"$selectMultiple.activeMatchIndex = $index;\" ng-class=\"{\'btn-primary\':$selectMultiple.activeMatchIndex === $index, \'select-locked\':$select.isLocked(this, $index)}\" ui-select-sort=\"$select.selected\"><span class=\"close ui-select-match-close\" ng-hide=\"$select.disabled\" ng-click=\"$selectMultiple.removeChoice($index)\">&nbsp;&times;</span> <span uis-transclude-append=\"\"></span></span></span></span>");
+$templateCache.put("bootstrap/match.tpl.html","<div class=\"ui-select-match\" ng-hide=\"$select.open && $select.searchEnabled\" ng-disabled=\"$select.disabled\" ng-class=\"{\'btn-default-focus\':$select.focus}\"><span tabindex=\"-1\" class=\"btn btn-default form-control ui-select-toggle\" aria-label=\"{{ $select.baseTitle }} activate\" ng-disabled=\"$select.disabled\" ng-click=\"$select.activate()\" style=\"outline: 0;\"><span ng-show=\"$select.isEmpty()\" class=\"ui-select-placeholder text-muted\">{{$select.placeholder}}</span> <span ng-hide=\"$select.isEmpty()\" class=\"ui-select-match-text pull-left\" ng-class=\"{\'ui-select-allow-clear\': $select.allowClear && !$select.isEmpty()}\" ng-transclude=\"\"></span> <i class=\"caret pull-right\" ng-click=\"$select.toggle($event)\"></i> <a ng-show=\"$select.allowClear && !$select.isEmpty() && ($select.disabled !== true)\" aria-label=\"{{ $select.baseTitle }} clear\" style=\"margin-right: 10px\" ng-click=\"$select.clear($event)\" class=\"btn btn-xs btn-link pull-right\"><i class=\"glyphicon glyphicon-remove\" aria-hidden=\"true\"></i></a></span></div>");
+$templateCache.put("bootstrap/no-choice.tpl.html","<ul class=\"ui-select-no-choice dropdown-menu\" ng-show=\"$select.items.length == 0\"><li ng-transclude=\"\"></li></ul>");
+$templateCache.put("bootstrap/select-multiple.tpl.html","<div class=\"ui-select-container ui-select-multiple ui-select-bootstrap dropdown form-control\" ng-class=\"{open: $select.open}\"><div><div class=\"ui-select-match\"></div><input type=\"search\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" class=\"ui-select-search input-xs\" placeholder=\"{{$selectMultiple.getPlaceholder()}}\" ng-disabled=\"$select.disabled\" ng-click=\"$select.activate()\" ng-model=\"$select.search\" role=\"combobox\" aria-expanded=\"{{$select.open}}\" aria-label=\"{{$select.baseTitle}}\" ng-class=\"{\'spinner\': $select.refreshing}\" ondrop=\"return false;\"></div><div class=\"ui-select-choices\"></div><div class=\"ui-select-no-choice\"></div></div>");
+$templateCache.put("bootstrap/select.tpl.html","<div class=\"ui-select-container ui-select-bootstrap dropdown\" ng-class=\"{open: $select.open}\"><div class=\"ui-select-match\"></div><span ng-show=\"$select.open && $select.refreshing && $select.spinnerEnabled\" class=\"ui-select-refreshing {{$select.spinnerClass}}\"></span> <input type=\"search\" autocomplete=\"off\" tabindex=\"-1\" aria-expanded=\"true\" aria-label=\"{{ $select.baseTitle }}\" aria-owns=\"ui-select-choices-{{ $select.generatedId }}\" class=\"form-control ui-select-search\" ng-class=\"{ \'ui-select-search-hidden\' : !$select.searchEnabled }\" placeholder=\"{{$select.placeholder}}\" ng-model=\"$select.search\" ng-show=\"$select.open\"><div class=\"ui-select-choices\"></div><div class=\"ui-select-no-choice\"></div></div>");
+$templateCache.put("select2/choices.tpl.html","<ul tabindex=\"-1\" class=\"ui-select-choices ui-select-choices-content select2-results\"><li class=\"ui-select-choices-group\" ng-class=\"{\'select2-result-with-children\': $select.choiceGrouped($group) }\"><div ng-show=\"$select.choiceGrouped($group)\" class=\"ui-select-choices-group-label select2-result-label\" ng-bind=\"$group.name\"></div><ul id=\"ui-select-choices-{{ $select.generatedId }}\" ng-class=\"{\'select2-result-sub\': $select.choiceGrouped($group), \'select2-result-single\': !$select.choiceGrouped($group) }\"><li role=\"option\" ng-attr-id=\"ui-select-choices-row-{{ $select.generatedId }}-{{$index}}\" class=\"ui-select-choices-row\" ng-class=\"{\'select2-highlighted\': $select.isActive(this), \'select2-disabled\': $select.isDisabled(this)}\"><div class=\"select2-result-label ui-select-choices-row-inner\"></div></li></ul></li></ul>");
+$templateCache.put("select2/match-multiple.tpl.html","<span class=\"ui-select-match\"><li class=\"ui-select-match-item select2-search-choice\" ng-repeat=\"$item in $select.selected track by $index\" ng-class=\"{\'select2-search-choice-focus\':$selectMultiple.activeMatchIndex === $index, \'select2-locked\':$select.isLocked(this, $index)}\" ui-select-sort=\"$select.selected\"><span uis-transclude-append=\"\"></span> <a href=\"javascript:;\" class=\"ui-select-match-close select2-search-choice-close\" ng-click=\"$selectMultiple.removeChoice($index)\" tabindex=\"-1\"></a></li></span>");
+$templateCache.put("select2/match.tpl.html","<a class=\"select2-choice ui-select-match\" ng-class=\"{\'select2-default\': $select.isEmpty()}\" ng-click=\"$select.toggle($event)\" aria-label=\"{{ $select.baseTitle }} select\"><span ng-show=\"$select.isEmpty()\" class=\"select2-chosen\">{{$select.placeholder}}</span> <span ng-hide=\"$select.isEmpty()\" class=\"select2-chosen\" ng-transclude=\"\"></span> <abbr ng-if=\"$select.allowClear && !$select.isEmpty()\" class=\"select2-search-choice-close\" ng-click=\"$select.clear($event)\"></abbr> <span class=\"select2-arrow ui-select-toggle\"><b></b></span></a>");
+$templateCache.put("select2/no-choice.tpl.html","<div class=\"ui-select-no-choice dropdown\" ng-show=\"$select.items.length == 0\"><div class=\"dropdown-content\"><div data-selectable=\"\" ng-transclude=\"\"></div></div></div>");
+$templateCache.put("select2/select-multiple.tpl.html","<div class=\"ui-select-container ui-select-multiple select2 select2-container select2-container-multi\" ng-class=\"{\'select2-container-active select2-dropdown-open open\': $select.open, \'select2-container-disabled\': $select.disabled}\"><ul class=\"select2-choices\"><span class=\"ui-select-match\"></span><li class=\"select2-search-field\"><input type=\"search\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" role=\"combobox\" aria-expanded=\"true\" aria-owns=\"ui-select-choices-{{ $select.generatedId }}\" aria-label=\"{{ $select.baseTitle }}\" aria-activedescendant=\"ui-select-choices-row-{{ $select.generatedId }}-{{ $select.activeIndex }}\" class=\"select2-input ui-select-search\" placeholder=\"{{$selectMultiple.getPlaceholder()}}\" ng-disabled=\"$select.disabled\" ng-hide=\"$select.disabled\" ng-model=\"$select.search\" ng-click=\"$select.activate()\" style=\"width: 34px;\" ondrop=\"return false;\"></li></ul><div class=\"ui-select-dropdown select2-drop select2-with-searchbox select2-drop-active\" ng-class=\"{\'select2-display-none\': !$select.open || $select.items.length === 0}\"><div class=\"ui-select-choices\"></div></div></div>");
+$templateCache.put("select2/select.tpl.html","<div class=\"ui-select-container select2 select2-container\" ng-class=\"{\'select2-container-active select2-dropdown-open open\': $select.open, \'select2-container-disabled\': $select.disabled, \'select2-container-active\': $select.focus, \'select2-allowclear\': $select.allowClear && !$select.isEmpty()}\"><div class=\"ui-select-match\"></div><div class=\"ui-select-dropdown select2-drop select2-with-searchbox select2-drop-active\" ng-class=\"{\'select2-display-none\': !$select.open}\"><div class=\"search-container\" ng-class=\"{\'ui-select-search-hidden\':!$select.searchEnabled, \'select2-search\':$select.searchEnabled}\"><input type=\"search\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" ng-class=\"{\'select2-active\': $select.refreshing}\" role=\"combobox\" aria-expanded=\"true\" aria-owns=\"ui-select-choices-{{ $select.generatedId }}\" aria-label=\"{{ $select.baseTitle }}\" class=\"ui-select-search select2-input\" ng-model=\"$select.search\"></div><div class=\"ui-select-choices\"></div><div class=\"ui-select-no-choice\"></div></div></div>");
+$templateCache.put("selectize/choices.tpl.html","<div ng-show=\"$select.open\" class=\"ui-select-choices ui-select-dropdown selectize-dropdown\" ng-class=\"{\'single\': !$select.multiple, \'multi\': $select.multiple}\"><div class=\"ui-select-choices-content selectize-dropdown-content\"><div class=\"ui-select-choices-group optgroup\"><div ng-show=\"$select.isGrouped\" class=\"ui-select-choices-group-label optgroup-header\" ng-bind=\"$group.name\"></div><div role=\"option\" class=\"ui-select-choices-row\" ng-class=\"{active: $select.isActive(this), disabled: $select.isDisabled(this)}\"><div class=\"option ui-select-choices-row-inner\" data-selectable=\"\"></div></div></div></div></div>");
+$templateCache.put("selectize/match-multiple.tpl.html","<div class=\"ui-select-match\" data-value=\"\" ng-repeat=\"$item in $select.selected track by $index\" ng-click=\"$selectMultiple.activeMatchIndex = $index;\" ng-class=\"{\'active\':$selectMultiple.activeMatchIndex === $index}\" ui-select-sort=\"$select.selected\"><span class=\"ui-select-match-item\" ng-class=\"{\'select-locked\':$select.isLocked(this, $index)}\"><span uis-transclude-append=\"\"></span> <span class=\"remove ui-select-match-close\" ng-hide=\"$select.disabled\" ng-click=\"$selectMultiple.removeChoice($index)\">&times;</span></span></div>");
+$templateCache.put("selectize/match.tpl.html","<div ng-hide=\"$select.searchEnabled && ($select.open || $select.isEmpty())\" class=\"ui-select-match\"><span ng-show=\"!$select.searchEnabled && ($select.isEmpty() || $select.open)\" class=\"ui-select-placeholder text-muted\">{{$select.placeholder}}</span> <span ng-hide=\"$select.isEmpty() || $select.open\" ng-transclude=\"\"></span></div>");
+$templateCache.put("selectize/no-choice.tpl.html","<div class=\"ui-select-no-choice selectize-dropdown\" ng-show=\"$select.items.length == 0\"><div class=\"selectize-dropdown-content\"><div data-selectable=\"\" ng-transclude=\"\"></div></div></div>");
+$templateCache.put("selectize/select-multiple.tpl.html","<div class=\"ui-select-container selectize-control multi plugin-remove_button\" ng-class=\"{\'open\': $select.open}\"><div class=\"selectize-input\" ng-class=\"{\'focus\': $select.open, \'disabled\': $select.disabled, \'selectize-focus\' : $select.focus}\" ng-click=\"$select.open && !$select.searchEnabled ? $select.toggle($event) : $select.activate()\"><div class=\"ui-select-match\"></div><input type=\"search\" autocomplete=\"off\" tabindex=\"-1\" class=\"ui-select-search\" ng-class=\"{\'ui-select-search-hidden\':!$select.searchEnabled}\" placeholder=\"{{$selectMultiple.getPlaceholder()}}\" ng-model=\"$select.search\" ng-disabled=\"$select.disabled\" aria-expanded=\"{{$select.open}}\" aria-label=\"{{ $select.baseTitle }}\" ondrop=\"return false;\"></div><div class=\"ui-select-choices\"></div><div class=\"ui-select-no-choice\"></div></div>");
+$templateCache.put("selectize/select.tpl.html","<div class=\"ui-select-container selectize-control single\" ng-class=\"{\'open\': $select.open}\"><div class=\"selectize-input\" ng-class=\"{\'focus\': $select.open, \'disabled\': $select.disabled, \'selectize-focus\' : $select.focus}\" ng-click=\"$select.open && !$select.searchEnabled ? $select.toggle($event) : $select.activate()\"><div class=\"ui-select-match\"></div><input type=\"search\" autocomplete=\"off\" tabindex=\"-1\" class=\"ui-select-search ui-select-toggle\" ng-class=\"{\'ui-select-search-hidden\':!$select.searchEnabled}\" ng-click=\"$select.toggle($event)\" placeholder=\"{{$select.placeholder}}\" ng-model=\"$select.search\" ng-hide=\"!$select.isEmpty() && !$select.open\" ng-disabled=\"$select.disabled\" aria-label=\"{{ $select.baseTitle }}\"></div><div class=\"ui-select-choices\"></div><div class=\"ui-select-no-choice\"></div></div>");}]);
\ No newline at end of file
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/api_doc.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/api_doc.html
deleted file mode 100644 (file)
index 342406c..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-  ============LICENSE_START==========================================
-  ===================================================================
-  Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
-  ===================================================================
-  Unless otherwise specified, all software contained herein is licensed
-  under the Apache License, Version 2.0 (the "License");
-  you may not use this software 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.
-  ============LICENSE_END============================================
- -->
-<div id="page-content">
-               <iframe  scrolling="yes" frameborder="0" style="width:100%; height: 800px;" 
-               ng-src="api-specs.html">
-       </iframe>
-</div>
\ No newline at end of file
index ebb35cd..f29d7ad 100644 (file)
@@ -1,30 +1,14 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *******************************************************************************/
-
 /* Angular application for the EC Dashboard web UI */
 var appDS2 = angular.module("abs", 
                [
                        'ngCookies', 'ngRoute', 'ngMessages','ngSanitize',
-                       'ui.bootstrap', 'ui.bootstrap.modal',
+                       'ui.bootstrap', 'ui.bootstrap.modal', 'ui.select',
                        'b2b.att',
-                       'modalServices'
+                       'modalServices', 'LocalStorageModule'
                ]
-       );
+       ).config(function($sceDelegateProvider) {
+                 $sceDelegateProvider.resourceUrlWhitelist(['**']);
+       }).config(['localStorageServiceProvider', function(localStorageServiceProvider) {
+        localStorageServiceProvider.setPrefix('eom')
+        .setStorageType('sessionStorage');
+  }]);
index 65495f1..cfa8be7 100644 (file)
@@ -1,24 +1,3 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *******************************************************************************/
-
 appDS2.factory('ControllerService', function ($http, $q, $log) {
        return {
                /**
@@ -39,20 +18,20 @@ appDS2.factory('ControllerService', function ($http, $q, $log) {
                                return $q.reject(error.statusText);
                        });
                },
-               getApiSwaggerSpec: function() {
-                       return $http({
-                               method: 'GET',
-                               url: 'nb-api/api-docs',
-                               cache: true,
-                               responseType: 'json'
-                       }).then(function(response) {
-                                       return response.data;
-                       }, 
-                       function(error) {
-                               $log.error('ControllerService.getApiSwaggerSpec failed: ' + JSON.stringify(error));
-                               return $q.reject(error.statusText);
-                       });                     
-               },
+    getApiSwaggerSpec: function() {
+      return $http({
+        method: 'GET',
+        url: 'api-docs',
+        cache: true,
+        responseType: 'json'
+      }).then(function(response) {
+          return response.data;
+      }, 
+      function(error) {
+        $log.error('ControllerService.getApiSwaggerSpec failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });     
+    },
                /**
                 * Gets the cloudify tenant names.
                 * 
@@ -74,70 +53,114 @@ appDS2.factory('ControllerService', function ($http, $q, $log) {
                                return $q.reject(error.statusText);
                        });
                },
+               getConsulLink: function() {
+      return $http({
+        method: 'GET',
+        url: 'consul_url',
+        cache: false,
+        responseType: 'text'
+      }).then(function(response) {
+        if (response.data == null) 
+          return $q.reject('ControllerService.getConsulLink: response.data null or not object');
+        else 
+          return response.data;
+      }, 
+      function(error) {
+        $log.error('ControllerService.getConsulLink failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });
+               },
                /**
                 * Gets the ops tools info
                 * 
                 */
-               getOpsUrls: function() {
+               getDcaeLinks: function() {
                        return $http({
                                method: 'GET',
-                               url: 'ops',
-                               cache: true,
-                               responseType: 'json'
+                               url: 'dcae_links',
+                               cache: false,
+                               responseType: 'text'
                        }).then(function(response) {
-                               if (response.data == null || typeof response.data != 'object'
-                                       return $q.reject('ControllerService.getOpsUrls: response.data null or not object');
+                               if (response.data == null) 
+                                       return $q.reject('ControllerService.getDcaeLinks: response.data null or not object');
                                else 
                                        return response.data;
                        }, 
                        function(error) {
-                               $log.error('ControllerService.getOpsUrls failed: ' + JSON.stringify(error));
+                               $log.error('ControllerService.getDcaeLinks failed: ' + JSON.stringify(error));
                                return $q.reject(error.statusText);
                        });
                },
-               /**
-                * Gets ECOMP-C Endpoint objects.
-                * No provision for pagination here.
-                * @return {JSON} Response object from remote side
-                */
-               getControllers: function() {
-                       // cache control for IE
-                       var cc = "?cc=" + new Date().getTime().toString();
+
+               getOpsToolUrls: function() {
                        return $http({
-                                       method: 'GET',
-                                       url: 'controllers' + cc,
-                                       cache: true,
-                                       responseType: 'json' 
+                               method: 'GET',
+                               url: 'ops_links',
+                               cache: false,
+                               responseType: 'json'
                        }).then(function(response) {
                                if (response.data == null || typeof response.data != 'object') 
-                                       return $q.reject('ControllerService.getControllers: response.data null or not object');
+                                       return $q.reject('ControllerService.getOpsToolUrls: response.data null or not object');
                                else 
                                        return response.data;
                        }, 
                        function(error) {
-                               $log.error('ControllerService.getControllers failed: ' + JSON.stringify(error));
+                               $log.error('ControllerService.getOpsToolUrls failed: ' + JSON.stringify(error));
                                return $q.reject(error.statusText);
-                       });
+                       });                             
                },
                
-               setControllerSelection: function(row) {
-                       // $log.debug('ControllerService.setControllerSelection: invoked with ' + JSON.stringify(row));
+               //Get the links from database table along with site/tenant list
+               getOpsToolMenuLinks: function() {
                        return $http({
-                                       method: 'POST',
-                                       url: 'controllers',
-                                       data: row,
-                                       responseType: 'json' 
+                               method: 'GET',
+                               url: 'ops_menu_links',
+                               cache: false,
+                               responseType: 'json'
                        }).then(function(response) {
                                if (response.data == null || typeof response.data != 'object') 
-                                       return $q.reject('ControllerService.setControllerSelection: response.data null or not object');
+                                       return $q.reject('ControllerService.getOpsToolMenuLinks: response.data null or not object');
                                else 
                                        return response.data;
                        }, 
                        function(error) {
-                               $log.error('ControllerService.setControllerSelection failed: ' + JSON.stringify(error));
+                               $log.error('ControllerService.getOpsToolMenuLinks failed: ' + JSON.stringify(error));
                                return $q.reject(error.statusText);
-                       });
-               }               
-               
+                       });                             
+               },              
+               getUserRoleData: function() {
+      return $http({
+        method: 'GET',
+        url: 'user-role-details',
+        cache: false,
+        responseType: 'json'
+      }).then(function(response) {
+        if (response.data == null || typeof response.data != 'object') 
+          return $q.reject('ControllerService.getUserRoleData: response.data null or not object');
+        else 
+          return response.data;
+      }, 
+      function(error) {
+        $log.error('ControllerService.getUserRoleData failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      }); 
+               },
+               getPluginsCount: function() {
+      return $http({
+        method: 'GET',
+        url: 'plugins-count',
+        cache: false,
+        responseType: 'json'
+      }).then(function(response) {
+        if (response.data == null || typeof response.data != 'object') 
+          return $q.reject('ControllerService.getPluginsCount: response.data null or not object');
+        else 
+          return response.data;
+      }, 
+      function(error) {
+        $log.error('ControllerService.getPluginsCount failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });                
+               }       
        };
 });
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions-view-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions-view-controller.js
deleted file mode 100644 (file)
index 2491e50..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-appDS2.controller('executionsViewController', function($scope, $rootScope, ControllerService, $modal, ExecutionService, $log) {
-       
-       $scope.parent = { 'blueprint_id': 'Root', 'parent': 'parent' };
-       $scope.ecdapp = {};
-       $scope.ecdapp.isDataLoading = false;
-       $scope.ecdapp.appLabel = "";
-       $rootScope.tenantList = {
-               tenant: '',
-               data: {}
-       };
-       var debug = false;
-       
-       var getTenants = function() {
-               ControllerService.getTenants()
-                       .then(function(jsonObj) {
-                               if (jsonObj.error) {
-                                       $log.error("executionsViewController.getTenants failed: " + jsonObj.error);
-                                       $scope.ecdapp.isRequestFailed = true;
-                                       $scope.ecdapp.errMsg = jsonObj.error;
-                                       $scope.ecdapp.tableData = [];
-                               } else {
-                                       $rootScope.tenantList.data = jsonObj.items;
-                                       $rootScope.tenantList.tenant = jsonObj.items[0].name;
-                               }                       
-                       }, function(error) {
-                               $log.error("executionsViewController.loadTable failed: " + error);
-                               $scope.ecdapp.isRequestFailed = true;
-                               $scope.ecdapp.errMsg = error;
-                       });
-               };
-
-       var getAppLabel = function() {
-               ControllerService.getAppLabel().then(function(jsonObj) {
-                       if (debug)
-                               $log.debug("Controller.getAppLabel succeeded: " + JSON.stringify(jsonObj));
-                       $scope.ecdapp.appLabel = jsonObj;
-               }, function(error) {
-                       $log.error("Controller.getAppLabel failed: " + error);
-               });
-       };
-       // Initialize the page
-       getAppLabel();
-       getTenants();
-
-});
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions_view.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/executions_view.html
deleted file mode 100644 (file)
index 5623b1c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<div id="page-content">
-
-       <h4 class="heading-page" id="controllers">DCAE Dashboard</h4>
-</div>
-
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/http-interceptor.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/http-interceptor.js
deleted file mode 100644 (file)
index 0f5410d..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-appDS2.factory('httpInterceptor', function ($q, $rootScope, $location) {
-        return {
-            'request': function (config) {
-                return config;
-            },
-               /*
-            'requestError': function (rejection) {
-            },
-            */
-            'response': function (response) {
-                if (response.data == null) {
-                       var loc = location.pathname;
-                       console.log("location path name: " + loc);
-                       var loc1 = loc.replace("/", "");
-                       var loc2 = loc1.replace("/ecd", "/login.htm");
-                       console.log("location url: " + loc2);
-                    alert("Your session has expired. Please log in again...");
-                    location.replace("/"+loc2);
-                }
-                return response;
-            },
-            // optional method
-            'responseError': function (rejection) {
-            }
-        };
-    })
-    .config(function($httpProvider) {
-                 $httpProvider.interceptors.push('httpInterceptor');
-       });
\ No newline at end of file
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-instances-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-instances-controller.js
deleted file mode 100644 (file)
index f07d1b3..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *  ECOMP is a trademark and service mark of AT&T Intellectual Property.
- *******************************************************************************/
-appDS2.controller('selectEcompcController', function(
-       $scope, $rootScope, $log, $modalInstance, message, ControllerService) {
-
-       // message brings the table items
-       
-       'use strict';
-
-       // Set to true for verbose output
-       var debug = false;
-       
-       // this object holds data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.tableData = message.items;
-
-       // Populate the model that drives the radio buttons.
-       // Radio buttons require a model with the value of the button
-       // that is selected.  The data comes across with a boolean
-       // indicator on each row, selected or not, which is useless
-       // for driving the radio buttons.  This model uses the URL
-       // as the unique value.
-       $scope.ecdapp.radiobutton = {
-               url : null
-       };
-       for (var rowNum in message.items) {
-               let row = message.items[rowNum];
-               if (debug)
-                       $log.debug('selectEcompcController: row is ' + JSON.stringify(row));
-               if (row.selected)
-                       $scope.ecdapp.radiobutton.url = row.url;
-       }
-       
-       /**
-        * Handles a click on radio button to select a controller.
-        */
-       $scope.ecdapp.selectController = function(row) {
-               if (debug)
-                       $log.debug('selectController: row is ' + JSON.stringify(row));
-               if (row == null || row.url == null)
-                       $log.error('selectController invoked with bad argument');
-               else
-                       ControllerService.setControllerSelection(row).then(function(data) {
-                               $rootScope.$broadcast('controllerChange', {name: row.name})
-                       },
-                       function(error) {
-                               $log.error('selectController failed: ' + error);
-                       });
-       };
-       
-});
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-router.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-router.js
deleted file mode 100644 (file)
index 0b43341..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * =============LICENSE_START=========================================================
- *
- * =================================================================================
- *  Copyright (c) 2020 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- *  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.
- * ============LICENSE_END=========================================================
- *
- *******************************************************************************/
-appDS2.config(function($routeProvider) {
-       $routeProvider
-       .when('/api', { 
-               templateUrl: 'app/ccsdk/home/api_doc.html',
-               controller : ''
-       })
-       .when('/api-spec', { 
-               templateUrl: 'app/ccsdk/home/rest-api-spec.html',
-               controller : 'apiDocsController'
-       })
-       .when('/ibp', { 
-               templateUrl: 'app/ccsdk/inventory/inventory_blueprint_table.html',
-               controller : 'inventoryBlueprintTableController'
-       })
-       .when('/idep', { 
-               templateUrl: 'app/ccsdk/inventory/inventory_deployment_table.html',
-               controller : 'inventoryDeploymentTableController'
-       })
-       .when('/idep/:depId', { 
-               templateUrl: 'app/ccsdk/inventory/inventory_deployment_table.html',
-               controller : 'inventoryDeploymentTableController'
-       })
-       .when('/sh', { 
-               templateUrl: 'app/ccsdk/consul/service_health_table.html',
-               controller : 'serviceHealthTableController'
-       })
-       .when('/nh', { 
-               templateUrl: 'app/ccsdk/consul/node_table.html',
-               controller : 'nodeTableController'
-       })
-       .when('/dc', { 
-               templateUrl: 'app/ccsdk/consul/datacenter_table.html',
-               controller : 'datacenterTableController'
-       })
-       .when('/profile/:profileId', {
-               templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html',
-               controller: 'selfProfileController'
-       })
-       .when('/profile_search', {
-               templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/profile_searchDS2.html',
-               controller : "profileSearchCtrlDS2"
-       })
-       .when('/post_search', {
-               templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/post.html',
-               controller: 'postController'
-       })
-       .when('/self_profile', {
-               templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-profile/self_profile.html',
-               controller: 'selfProfileController'
-       })      
-       .when('/role_list', {
-               templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/role_list.html',
-               controller : 'adminController'
-       })
-       .when('/role_function_list', {
-               templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/role-function.html',
-               controller : "adminController"
-       })
-       .when('/jcs_admin', {
-               templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/jcs_admin.html',
-               controller: 'adminController'
-       })
-       .when('/admin_menu_edit', {
-               templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/admin-menu-edit.html',
-               controller: 'AdminMenuEditController'
-       })
-       .when('/usage_list', {
-               templateUrl: 'app/fusion/scripts/DS2-view-models/ds2-admin/usage.html',
-               controller: 'usageListControllerDS2'
-       })
-       .otherwise({
-               templateUrl: 'app/ccsdk/home/executions_view.html',
-               controller : 'executionsViewController'
-       })
-       ;
-
-});
\ No newline at end of file
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-style.css b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom-style.css
deleted file mode 100644 (file)
index a4e9a97..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-/* Styles for ECOMP Controller Dashboard */
-
-.content-container {
-       min-height: 650px;
-       width: calc(100% - 50px);
-}
-
-.ecd-error-message {
-       font-size: 14px;
-       font-weight: bold;
-       color: red;
-}
-
-.ecd-icon-display {
-       font-size: 18px;
-}
-
-.ecd-icon-action {
-       font-size: 18px;
-}
-
-.ecd-icon-action:hover {
-       color: red;
-       text-decoration: none;
-}
-
-.selected {
-    background-color:black;
-    color:white;
-    font-weight:bold;
-}
-.red-background {
-   background-color: #ff0000b3;
- }
-.green-background {
-   background-color: #bbf0bb;
- } 
-.td-error {
-       border-top: 5px dotted red;
-       border-bottom: 5px dotted red;
- }
-.menu {
-       display: none;
-       z-index: 1000;
-       border: 1px dotted;
-       border-radius: 5px;
-       padding: 10px;
-       width: 50%;
-       background: azure;
-       position: fixed;
-       overflow: scroll;
-}
-
-.show-menu {
-       z-index: 800;
-}
-
-#show-menu {
-       display: none;
-}
-
-#show-menu:checked ~ .menu {
-       display: block;
-}
-
-#show-menu:checked ~ .show-menu {
-       color: blue;
-}
-
-.menu-off {
-       position: fixed;
-       left: 0;
-       right: 0;
-       top: 0;
-       bottom: 0;
-       z-index: 700;
-       display: none;
-}
-
-.menu-off {
-       display: none;
-}
-
-#show-menu:checked ~ .menu-off {
-       display: block;
-}
-
-#show-menu:checked ~ .show-menu {
-       display: none;
-}
-
-.menu-off input[type=checkbox]:checked ~ .menu {
-       display: none;
-}
-
-.menu-off input[type=checkbox]:checked ~ .show-menu {
-       display: block;
-}
-
-td > .btn-group {
-       min-width: 0;
-       width: auto;
-}
-
-.dropup,
-.dropdown {
-  position: relative;
-}
-.dropdown-toggle:focus {
-  outline: 0;
-}
-.dropdown-menu {
-  position: absolute;
-  top: 100%;
-  left: 0;
-  z-index: 1000;
-  display: none;
-  float: left;
-  min-width: 160px;
-  padding: 5px 0;
-  margin: 2px 0 0;
-  font-size: 14px;
-  text-align: left;
-  list-style: none;
-  background-color: #fff;
-  -webkit-background-clip: padding-box;
-          background-clip: padding-box;
-  border: 1px solid #ccc;
-  border: 1px solid rgba(0, 0, 0, .15);
-  border-radius: 4px;
-  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
-          box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
-}
-.dropdown-menu.pull-right {
-  right: 0;
-  left: auto;
-}
-.dropdown-menu .divider {
-  height: 1px;
-  margin: 9px 0;
-  overflow: hidden;
-  background-color: #e5e5e5;
-}
-.dropdown-menu > li > a {
-  display: block;
-  padding: 3px 20px;
-  clear: both;
-  font-weight: normal;
-  line-height: 1.42857143;
-  color: #333;
-  white-space: nowrap;
-}
-.dropdown-menu > li > a:hover,
-.dropdown-menu > li > a:focus {
-  color: #262626;
-  text-decoration: none;
-  background-color: #f5f5f5;
-}
-.dropdown-menu > .active > a,
-.dropdown-menu > .active > a:hover,
-.dropdown-menu > .active > a:focus {
-  color: #fff;
-  text-decoration: none;
-  background-color: #337ab7;
-  outline: 0;
-}
-.dropdown-menu > .disabled > a,
-.dropdown-menu > .disabled > a:hover,
-.dropdown-menu > .disabled > a:focus {
-  color: #777;
-}
-.dropdown-menu > .disabled > a:hover,
-.dropdown-menu > .disabled > a:focus {
-  text-decoration: none;
-  cursor: not-allowed;
-  background-color: transparent;
-  background-image: none;
-  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
-}
-.open > .dropdown-menu {
-  display: block;
-}
-.open > a {
-  outline: 0;
-}
-.dropdown-menu-right {
-  right: 0;
-  left: auto;
-}
-.dropdown-menu-left {
-  right: auto;
-  left: 0;
-}
-.dropdown-header {
-  display: block;
-  padding: 3px 20px;
-  font-size: 12px;
-  line-height: 1.42857143;
-  color: #777;
-  white-space: nowrap;
-}
-.dropdown-backdrop {
-  position: fixed;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  z-index: 990;
-}
-.pull-right > .dropdown-menu {
-  right: 0;
-  left: auto;
-}
-.dropup .caret,
-.navbar-fixed-bottom .dropdown .caret {
-  content: "";
-  border-top: 0;
-  border-bottom: 4px dashed;
-  border-bottom: 4px solid \9;
-}
-.dropup .dropdown-menu,
-.navbar-fixed-bottom .dropdown .dropdown-menu {
-  top: auto;
-  bottom: 100%;
-  margin-bottom: 2px;
-}
-@media (min-width: 768px) {
-  .navbar-right .dropdown-menu {
-    right: 0;
-    left: auto;
-  }
-  .navbar-right .dropdown-menu-left {
-    right: auto;
-    left: 0;
-  }
-}
-
-.dropdown-menu li {
-       margin-bottom: 10px;
-}
-
-.dropdown-menu li div {
-       padding-left: 5px;
-}
-
-.dropdown-menu li div i {
-       margin-right: 5px;
-}
-
-td > .btn-group > .btn {
-       min-width: 0;
-       color: #0568ae;
-}
-
-td > .btn-group > .btn> i {
-       font-size: 30px;
-}
-
-li > a.active {
-       font-weight: bolder;
-       outline: thin dotted #666;
-}
-
-tr:hover {
-       background-color: #f2f2f2;
-}
-
-tr:focus {
-       background-color: #f2f2f2;
-}
-
-.modalwrapper.modal-docked .modal-jumbo {
-    max-height: 100%;
-    height: 100%;
-    overflow: hidden;
-    top: 0;
-    width: 100%;
-    max-width: 100%;
-}
-
-#addAppDiv {
-       padding-left: 10px;
-    background: lightgray;
-    border-radius: 5px;
-    padding-bottom: 15px;
-}
-
-.field-group.error .error-msg {
-       color: red;
-    display: block;
-    font-size: 14px;
-    line-height: 14px;
-    font-family: "Omnes-ATT-W02-Medium";
-    position: relative;
-    padding-left: 18px;
-    margin-top: 10px;
-}
-
-.heading-page {
-       margin-bottom: 20px;
-}
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_instances_popup.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/oom_instances_popup.html
deleted file mode 100644 (file)
index bc523aa..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-<script type="text/ng-template" id="ecompc_instances_popup.html">
-<style>
-       .ecd-parameter-table
-       {
-               border:   1px;
-               width:  550px;
-               height: 225px;
-       overflow: auto;
-       }
-       .modal
-       {
-               display:block
-       }
-       .radio input:checked + .skin:after{
-               height: 22px;
-               width: 22px;
-       }
-       .close-button
-       {
-       background: #0568ae; 
-       color: #ffffff;"; 
-       }
-
-</style>
-
-       <div class="b2b-modal-header ng-scope">
-               <h1 class="heading-page" id="controllerInstance">Select ECOMP-C Instance</h1>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content"> 
-
-               <div b2b-table 
-               id="controllers-modal"
-                   class="b2b-table-div" 
-                   table-data="ecdapp.tableData" 
-               search-string="ecdapp.searchString" 
-                       current-page="ecdapp.currentPageIgnored"
-                       next-sort="ecdapp.nextSortIgnored">
-                       <table>                 
-                       <thead b2b-table-row type="header">     
-                                       <tr id="th-header-row">
-                                               <th b2b-table-header sortable="false">Selected</th>
-                                               <th b2b-table-header key="name">Name</th>
-                                               <th b2b-table-header key="url">URL</th>
-                                       </tr>
-                               </thead>
-                                       
-               <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData">
-                                       <tr id="tr-rowData">
-                                               <td b2b-table-body>
-                                       <label class="radio">
-                                               <input
-                                                       type="radio" 
-                                                                       name="ecdSelGroup" 
-                                                                       title="rowData.url"
-                                                                       ng-value="rowData.url" 
-                                                                       ng-model="ecdapp.radiobutton.url"
-                                                                       ng-change="ecdapp.selectController(rowData);">
-                                                               <i class="skin"></i>
-                                                               <span></span>
-                                       </label>
-                                               </td>
-                                               <td b2b-table-body
-                                                       ng-bind="rowData.name"/>
-                                               <td b2b-table-body
-                                                       ng-bind="rowData.url"/>
-                                       </tr>
-                               </tbody>
-                       </table>
-               </div>
-       </div>
-
-       <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-               <div class="cta-button-group in">
-                       <button class="btn btn-small close-button" type="button" ng-click="$close()">
-                               Close
-                       </button>
-               </div>
-       </div>
-
-</script>
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-controller.js
deleted file mode 100644 (file)
index 99005fb..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-appDS2.controller('treeViewController',function(
-               $scope, $rootScope, $log, $modal, ExecutionService, ControllerService){
-       
-       'use strict';
-
-       // Set to true for verbose output
-       var debug = false;
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.isDataLoading = false;
-       $scope.ecdapp.isRequestFailed = false;
-       $scope.orgChart = true;
-       $scope.status = '';
-       var selectedItem = {
-               name: ''
-       };
-       // Initial data as eye candy
-       $scope.orgChartData = [  { 'blueprint_id': 'Root', 'parent': 'parent' } ]; 
-       var controllersList = [];
-       
-       var getControllers = function(){
-               ControllerService.getControllers().then(function(jsonObj) {
-                       if (debug)
-                               $log.debug("treeViewController.getControllers succeeded: " + JSON.stringify(jsonObj));
-                       // Empty
-                       controllersList.length = 0;
-                       // Refill
-                       jsonObj.filter(function(d) {
-                               controllersList.push(d);
-                               if (d.selected)
-                                       selectedItem = d; 
-                               return;
-                       });
-                       $scope.ecdapp.loadTable();
-               }, function(error) {
-                       alert('Failed to load controllers. Please retry.');
-                       $log.error("treeViewController.getControllers failed: " + error);
-               });
-       }
-
-       /**
-        * Called from the directive when user picks a status value.
-        */
-       $scope.ecdapp.loadTable = function(status) {
-               $scope.ecdapp.isDataLoading = true;
-               $scope.status = status;
-               // Empty list and create the root controller item
-               $scope.orgChartData.length = 0;
-               $scope.orgChartData.push({
-                       "blueprint_id": selectedItem.name,
-                       "parent": "parent"
-               });
-               ExecutionService.getExecutionsByStatus(status).then(
-                               function(jsonObj) {
-                                       if (jsonObj.error) {
-                                               $log.error("treeViewController.loadTable failed: "
-                                                               + jsonObj.error);
-                                               $scope.ecdapp.isRequestFailed = true;
-                                               $scope.ecdapp.errMsg = jsonObj.error;
-                                       } else {
-                                               $scope.ecdapp.isRequestFailed = false;
-                                               $scope.ecdapp.errMsg = null;
-                                               for (var i=0; i < jsonObj.items.length; i++) {
-                                                       $scope.orgChartData.push(jsonObj.items[i]);                             
-                                               }
-                                               $scope.$broadcast('listenEvent', {data: $scope.orgChartData} );
-                                       }
-                                       $scope.ecdapp.isDataLoading = false;
-                               },
-                               function(error) {
-                                       $log.error("treeViewController.loadTable failed: "
-                                                       + error);
-                                       $scope.ecdapp.isRequestFailed = true;
-                                       $scope.ecdapp.errMsg = error;
-                                       $scope.ecdapp.isDataLoading = false;
-                               });
-       };
-
-       // Listens for change of the selected controller
-       $rootScope.$on('controllerChange', function(e, d){
-               $scope.orgChartData[0].blueprint_id = d.name;
-               $scope.$broadcast('listenEvent', {data: $scope.orgChartData});
-       })
-       
-       // Shows popup with list of controllers
-       $scope.ecdapp.showEcompCInstancesModalPopup = function() {
-               var modalInstance = $modal.open({
-                       templateUrl : 'ecompc_instances_popup.html',
-                       controller : 'selectEcompcController',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-medium',
-                       resolve : {
-                               message : function() {
-                                       return { items: controllersList }
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) { 
-                       // Always reload the table
-                       // $log.debug('modalInstance: reloading controllers');
-                       getControllers('active');
-               }, 
-               function(error) {
-                       // Should never happen
-                       $log.error('modalInstance: ERROR!?');
-               });
-       };
-       
-       // Populate the table on load.
-       getControllers('active');
-
-});
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-directive.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-directive.js
deleted file mode 100644 (file)
index 834026b..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-(function() {
-    'use strict';
-    
-   appDS2.directive("orgChart", supervisorOrgChart);
-    supervisorOrgChart.$inject = ['$http', '$templateCache', 'ExecutionService'];
-
-    function supervisorOrgChart($http, $templateCache, ExecutionService) {
-        return {
-            restrict: 'E',
-            scope: {
-                data: '=',
-                getCall: '&',
-                modalCall: '&',
-                status: '='
-            },
-
-            link: function(scope, elem, attrs) {
-                
-                scope.$on('listenEvent', function(event, data) {
-                       data = data.data;
-                       scope.data = data;
-                       $('.jOrgChart').remove();
-                       drawOrgChart(data);
-                });
-
-
-                var items = [],
-                    mCheck = [];
-                var currentZoom = 100;
-                var data = scope.data;
-                var selectedStatus = scope.status;
-                function statusSelectoin(status){
-                    $('#statusclick li').removeClass('active');
-                    scope.getCall()(status);
-                }
-
-                function drawOrgChart(data, supervisorOrg) {
-                    items = [];
-                    var itemHtml = "";
-                    for(var i=0; i<data.length; i++){
-                        loops(data[i]);
-                    }
-                    function loops(root) {
-                        var className;
-                        if (root.parent == "parent") {
-                            items.push("<li class='root '>" +
-                                "<div><div class='label_node' style='position:relative'>" +
-                                "<span class='' style='position:absolute; left:1px; top:5px'>"+
-                                "<div class='dropdown dd_"+root.id+"'>"+
-                                    "<div style='float: right;'>"+
-                                    "<button id='dd_"+root.id+"' class='btn btn-default dropdown-toggle icon-misc-filter' type='button' data-toggle='dropdown'>"+
-                                    "</button>"+
-                                    "<ul class='dropdown-menu' id='statusclick'>"+
-                                      "<li id='active'>Active</li>"+
-                                      "<li id='cancelled'>Cancelled</li>"+
-                                      "<li id='terminated'>Terminated</li>"+
-                                      "<li id='failed'>Failed</li>"+
-                                    "</ul>"+
-                                    "</div>"+
-                                    "</div>"+
-                                "</span>"+
-                                "<span style='position: absolute; font-size: 12px; left:30px; top:10px' class='title-span'>" + root.blueprint_id + "</span>"+
-                                            "<button id='dd_"+root.id+"' style='margin-top: 5px; position: absolute; right: 2px;' class='openmodal btn btn-default dropdown-toggle icon-controls-gear' " +
-                                            "type='button' data-toggle='dropdown'>"+
-                                            "</button>"+
-                                "</div></div></br>"+
-                                "<div style='padding-top:25px'><img src='app/ecdapp/images/ecomp-login-550x360.jpg' width='180' height='100'></div>"+
-                                "<div class='expandBtn'><span id='exp_"+root.id+"'><i class='icon-controls-add-maximize'></i></span></div><ul>");
-                        } else {
-                            itemHtml = "<li class='child'>"+
-                            "<div style='padding-top:3px'><span class='label_node'>"+
-                           
-                            "<span class='title-span'>" + root.blueprint_id + "</span>"+
-                            "<span class='icon-span ddIcon'>"+
-                                    "<div class='dropdown dd_"+root.id+"'>"+
-                                        "<div style='float: right; margin-top: -14px;'>"+
-                                        "<button id='dd_"+root.id+"' class='btn btn-default dropdown-toggle' type='button' data-toggle='dropdown'><i class='icon-people-preview'></i>"+
-                                        "<span id='dd_"+root.id+"'></span></button>"+
-                                        "<ul class='dropdown-menu'>"+
-                                          "<li><a tabindex='-1' href='javascript:void(0);'>Execution Id: " + root.id + "</a></li>"+
-                                          "<li><a tabindex='-1' href='javascript:void(0);'>Health Check Status: </a></li>"+
-                                          "<li><a tabindex='-1' href='javascript:void(0);'>Please click here for more information </a></li>"+                                        
-                                        "</ul>"+
-                                        "</div>"+
-                                  "</div>"+
-                            "</span>"+
-                            "</span></div></br>"+
-                            "<div style='padding-top:35px'><img src='app/ecdapp/images/ecomp.png' width='180' height='100'></div></li>";
-                            items.push(itemHtml);
-                        }
-                    } // End the generate html code
-
-                    items.push('</ul></li>');
-                    var listElem = $("<ul/>", {
-                        "class": "org",
-                        "style": "float:right;",
-                        html: items.join("")
-                    }).appendTo(elem);
-
-                    var opts = {
-                        chartElement: elem,
-                        rowcolor: false
-                    };
-                    //elem.html('');
-                    $(elem).find(".org").jOrgChart(opts);
-                    listElem.remove();
-                    
-                    setTimeout(function(){
-                        $('.dropdown .dropdown-toggle').on("click", function(e){
-                            var cls = '.'+ e.target.id;
-                            var subcls = cls + ' a.test';
-                            if($(cls).hasClass('open')){
-                                $(cls).removeClass('open');
-                                $(subcls).next('ul').css({display: 'none'});
-                            } else{
-                                $(cls).addClass('open');
-                            }
-                        });
-
-                        $('.dropdown-submenu a.test').on("mouseover", function(e){
-                            console.log("hi");
-                            $('#'+e.target.id).next('ul').toggle();
-                        });
-
-                        $('#statusclick li').click(function(event){
-                            statusSelectoin(event.target.id);
-                        })
-                        
-                        $('.openmodal').click(function(event){
-                               openModal();
-                        })
-                        
-                        $(document).on('click','.expandBtn', function(event, data) {
-                               event.stopImmediatePropagation()
-                            var $this = $(this);
-                            var $tr = $this.closest("tr");
-                            if ($tr.hasClass('contracted')) {
-                                $(this).addClass('fa-minus').removeClass('fa-plus');
-                                $tr.removeClass('contracted').addClass('expanded');
-                                $tr.nextAll("tr").css('visibility', '');
-                            } else {
-                                $(this).addClass('fa-plus').removeClass('fa-minus');
-                                $tr.removeClass('expanded').addClass('contracted');
-                                $tr.nextAll("tr").css('visibility', 'hidden');
-                            }
-                        });
-                        
-                        var selectedStatus = scope.status;
-                        if(selectedStatus){
-                               $('#'+selectedStatus).addClass('active');
-                        }
-                        
-                        function openModal(){
-                               scope.modalCall()();
-                        }
-
-                    },0);
-                }
-                                       
-               drawOrgChart(data);
-
-            },
-        };
-    };
-})();
\ No newline at end of file
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-style.css b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree-view-style.css
deleted file mode 100644 (file)
index 5a3e056..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/* Basic styling */
-
-::-webkit-scrollbar
-{
-  width: 12px;  /* for vertical scrollbars */
-  height: 7px; /* for horizontal scrollbars */
-}
-
-::-webkit-scrollbar-track
-{
-  background: rgba(0, 0, 0, 0.1);
-}
-
-::-webkit-scrollbar-thumb
-{
-  background: rgba(0, 0, 0, 0.5);
-}
-
-.orgChart .label_node{
-       padding-bottom: 5px;
-}
-
-.orgChart .icon-span{
-       float:left;width:25px;
-       padding-top: 3px;
-}
-.orgChart .title-span{
-       width:110px;float:left; font-size:14px;
-       padding-top: 3px;
-}
-
-/* Draw the lines */
-.jOrgChart{
-       position: relative;
-       /*  left: 245px; */
-       width:100%;
-       min-width: 100%;
-       overflow-x: auto;
-       
-}
-.jOrgChart .line {
-  height                : 20px;
-  width                 : 4px;
-}
-
-.jOrgChart .down {
-  background-color             : black;        
-  margin                               : 0px auto;
-}
-
-.jOrgChart .top {
-  border-top          : 3px solid black;
-}
-
-.jOrgChart button{
-       min-width               : 20px;
-       width                   : 20px;
-       height                  : 20px;
-       padding                 : 0;
-}
-
-.jOrgChart .dropdown{
-       display: inline-block;
-}
-
-.jOrgChart .downloadIcon{
-           position: relative;
-    left: 1px;
-    float:left;
-}
-
-.jOrgChart .ddIcon{
-       position: relative;
-    float: right;
-    top: 6px;
-}
-
-.jOrgChart .left {
-  border-right          : 2px solid black;
-}
-
-.jOrgChart .right {
-  border-left           : 2px solid black;
-}
-
-/* node cell */
-.jOrgChart td {
-  text-align            : center;
-  vertical-align        : top;
-  padding               : 0 !important;
-  border                               : none;
-  border-bottom         : 1px solid white;
-}
-
-/* The node */
-.jOrgChart .node {
-  background-color             : #efefef;
-  display               : inline-block;
-  width                 : 180px;
-  height                : 200px;
-  z-index                              : 10;
-  margin               : 0 2px;
-}
-
-.expandBtn {
-       background-color: #efefef;
-       padding-top:9px; 
-}
-
-/* jQuery drag 'n drop */
-
-.drag-active {
-  border-style                 : dotted !important;
-}
-
-.drop-hover {
-  border-style                 : solid !important;
-  border-color                         : #E05E00 !important;
-}
-
-#statusclick{
-       padding: 0 !important
-}
-
-#statusclick li {
-       padding :5px;
-}
-
-#statusclick li.active{
-       background: #337ab7;
-       color: white;
-}
\ No newline at end of file
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree_view.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/home/tree_view.html
deleted file mode 100644 (file)
index d5364e8..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<!-- Included bootstrap files at a page level to avoid issues with DS2 library -->
-<script src="app/ecdapp/external/bootstrap.min.js"></script>   
-<link rel="stylesheet" href="app/ecdapp/external/bootstrap.min.css"/>
-
-<div id="page-content">
-       
-       <org-chart data=orgChartData status="status" showOrgTable="showOrgTable" get-call="ecdapp.loadTable" modal-call="ecdapp.showEcompCInstancesModalPopup">
-       </org-chart>                    
-       <div ng-show="ecdapp.isDataLoading">
-               <div class="text-center" style="margin-bottom:20px;">
-               <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-               Please wait while the content loads.
-           </div>
-       </div>
-       <div ng-hide="ecdapp.isDataLoading">
-               <div ng-if="orgChartData.length == 1" class="col-xs-12 text-center" style="position:relative;">
-                       <b>No components found</b>
-               </div>
-       </div>
-       <div ng-show="ecdapp.isRequestFailed">
-               <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-       </div>  
-
-</div>
index fceab0e..b474348 100644 (file)
 appDS2.controller('inventoryBlueprintTableController', function(
-               $rootScope, $scope, $log, $modal, modalService, InventoryBlueprintService, InventoryDeploymentService) {
-       
-       'use strict';
-
-       // Controls logging in this controller
-       var debug = false;
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       // models for controls on screen
-       $scope.ecdapp.tableData = [];
-       $scope.ecdapp.currentPageNum = 1;       
-       $scope.ecdapp.viewPerPage = 10;
-       // other
-       $scope.ecdapp.errMsg = null;
-       $scope.ecdapp.isDataLoading = true;
-       $scope.ecdapp.isRequestFailed = false;
-       // sorting
-       $scope.ecdapp.sortBy = null;
-       // searching
-       $scope.ecdapp.searchBy = null;
-       
-       $scope.ecdapp.trackBpRowIndex = function(indx) {
-               $scope.ecdapp.tableData[indx].expanded = !$scope.ecdapp.tableData[indx].expanded;
-       };
-       
-       $scope.ecdapp.updateTable = function() {
-               $scope.ecdapp.isSrvcDataLoading = true;
-               var srvcTypIds = [];
-               var srvcIds = [];
-               var bpDepls =[];
-               var cloneGrid = $scope.ecdapp.tableData;        
-               angular.forEach($scope.ecdapp.tableData, function(item, index) {
-                         angular.forEach(item, function(value, key) {
-                                 if (key === "typeId") {
-                                         srvcTypIds.push(value); 
-                                 }       
-                         });
-         });
-               
-               InventoryBlueprintService.getDeploymentForBp(srvcTypIds)
-               .then(function(jsonObj) {
-               if (jsonObj.error) {
-                       $log.error("inventoryBlueprintController.updateTable failed: " + jsonObj.error);
-               } else {
-                       bpDepls = jsonObj;
-                       for (var typIndx = 0; typIndx < bpDepls.length; typIndx++) {
-                               srvcIds.push(bpDepls[typIndx].serviceRefList);
-                       }
-                       angular.forEach(cloneGrid, function(item, index) {
-                                 item.deployments = srvcIds[index];
-                                 item.expanded = false;
-               });
-               $scope.ecdapp.tableData = cloneGrid;
-               }
-               $scope.ecdapp.isSrvcDataLoading = false;
-       }, function(error) {
-               $log.error("inventoryBlueprintController.updateTable failed: " + error);
-               bpDepls = [];
-               $scope.ecdapp.isSrvcDataLoading = false;
-       });
-
-       }
-       
-       $scope.ecdapp.JSONToCSVConverter = function(blueprint) 
-       {
-      var array = typeof blueprint != 'object' ? JSON.parse(blueprint) : blueprint;
-      var str = '';
-      for (var i = 0; i < array.length; i++) {
-          var line = '';
-
-          for (var index in array[i]) {
-            line += array[i][index] + ',';
+    $rootScope, $scope, $log, $modal, modalService, ControllerService, $interval, $routeParams,
+    InventoryBlueprintService, InventoryDeploymentService, localStorageService) {
+
+  'use strict';
+
+  // Controls logging in this controller
+  var debug = false;
+  var stop;
+  
+  // this object holds all app data and functions
+  $scope.ecdapp = {};
+  // models for controls on screen
+  $scope.ecdapp.tableData = [];
+  $scope.ecdapp.currentPage = 1;       
+  $scope.ecdapp.viewPerPage = 10;
+  // other
+  $scope.ecdapp.errMsg = null;
+  $scope.ecdapp.isDataLoading = true;
+  $scope.ecdapp.isRequestFailed = false;
+  $scope.ecdapp.filterByUser = true;
+  // sorting
+  $scope.ecdapp.sortBy = null;
+
+  // searching
+  $scope.ecdapp.searchBy = $routeParams.bpId;
+  if ($scope.ecdapp.searchBy == undefined) {
+    $scope.ecdapp.searchBy = "owner:" + $scope.userId + ";";
+  } else {
+    if ($scope.ecdapp.searchBy.includes("owner")) {
+      if ($scope.ecdapp.searchBy.split(":")[1] === "group") {
+        $scope.ecdapp.filterByUser = false;
+        $scope.ecdapp.searchBy = undefined;
+      }
+    }    
+  }
+
+  $scope.ecdapp.searchString;
+  $scope.ecdapp.availableTenants = JSON.parse(localStorageService.get('tenants'));
+  $scope.ecdapp.isInternal = localStorageService.get('internal');
+  if ($scope.ecdapp.isInternal) {
+    $scope.ecdapp.components = JSON.parse(localStorageService.get('appComponents'));
+    $scope.ecdapp.apps = JSON.parse(localStorageService.get('apps'));
+    $scope.ecdapp.selectedApp;
+    $scope.ecdapp.selectedComp;
+    $scope.ecdapp.availableComp = JSON.parse(localStorageService.get('components'));
+  }
+  $scope.ecdapp.selectedBp;
+  $scope.ecdapp.availableBp = JSON.parse(localStorageService.get('bpNames'));
+
+  $scope.ecdapp.selectedOwner;
+
+  $scope.ecdapp.showingMoreFilters = false;
+
+  $scope.ecdapp.toggleMoreFilters = function() {      
+    $scope.ecdapp.showingMoreFilters = !$scope.ecdapp.showingMoreFilters;
+  };
+  
+  $scope.ecdapp.trackBpRowIndex = function(indx) {
+    $scope.ecdapp.tableData[indx].expanded = !$scope.ecdapp.tableData[indx].expanded;
+  };
+  $scope.ecdapp.updateTable = function() {
+    $scope.ecdapp.isSrvcDataLoading = true;
+    var srvcTypIds = [];
+    var srvcIds = [];
+    var bpDepls =[];
+    var cloneGrid = $scope.ecdapp.tableData;   
+    angular.forEach($scope.ecdapp.tableData, function(item, index) {
+      angular.forEach(item, function(value, key) {
+        if (key === "typeId") {
+          srvcTypIds.push(value); 
+        }        
+      });
+    });
+
+    InventoryBlueprintService.getDeploymentForBp(srvcTypIds)
+    .then(function(jsonObj) {
+      if (jsonObj.error) {
+        $log.error("inventoryBlueprintController.updateTable failed: " + jsonObj.error);
+      } else {
+        bpDepls = jsonObj;
+        for (var typIndx = 0; typIndx < bpDepls.length; typIndx++) {
+          srvcIds.push(bpDepls[typIndx].serviceRefList);
+        }
+        angular.forEach(cloneGrid, function(item, index) {
+          item.deployments = srvcIds[index];
+          item.expanded = false;
+        });
+        $scope.ecdapp.tableData = cloneGrid;
+      }
+      $scope.ecdapp.isSrvcDataLoading = false;
+    }, function(error) {
+      $log.error("inventoryBlueprintController.updateTable failed: " + error);
+      bpDepls = [];
+      $scope.ecdapp.isSrvcDataLoading = false;
+    });
+  }
+
+  $scope.ecdapp.JSONToCSVConverter = function(blueprint) {
+    var array = typeof blueprint != 'object' ? JSON.parse(blueprint) : blueprint;
+    var str = '';
+    for (var i = 0; i < array.length; i++) {
+      var line = '';
+      for (var index in array[i]) {
+        line += array[i][index] + ',';
+      }
+      line.slice(0, line.Length - 1);
+      str += line + '\r\n';
+    } 
+
+    var uri = 'data:text/csv;charset=utf-8,' + escape(str);
+    var fileName = 'exported';
+
+    var link = document.createElement("a");
+    link.href= uri;
+
+    link.style = "visibility:hidden";
+    link.download = fileName + ".csv";
+
+    document.body.appendChild(link);
+    link.click();
+    document.body.removeChild(link);
+  };
+
+  $scope.ecdapp.createcsv = function(blueprint) {
+    var bpArr =[];
+    bpArr.push(blueprint);
+    $scope.ecdapp.JSONToCSVConverter(bpArr);
+  };
+
+  $scope.ecdapp.exportJson = function(blueprint) {
+    var bpExportObj = {};
+    bpExportObj.application = blueprint.application;
+    bpExportObj.component = blueprint.component;
+    bpExportObj.typeName = blueprint.typeName;
+    bpExportObj.typeVersion = blueprint.typeVersion;
+    bpExportObj.blueprintTemplate = blueprint.blueprintTemplate;
+
+    var bpStr = JSON.stringify(bpExportObj);
+    var uri = 'data:text/json;charset=utf-8,' + escape(bpStr);
+    var fileName = blueprint.application + '_' + blueprint.component + 
+    '_' + blueprint.typeName + '_' + blueprint.typeVersion;
+
+    var link = document.createElement("a");
+    link.href= uri;
+
+    link.style = "visibility:hidden";
+    link.download = fileName + ".json";
+
+    document.body.appendChild(link);
+    link.click();
+    document.body.removeChild(link);
+  };
+
+  $scope.ecdapp.getTenants = function() {  
+      ControllerService.getTenants()
+      .then(function(jsonObj) {
+        if (jsonObj.error) {
+          $log.error("blueprintController.getTenants failed: " + jsonObj.error);
+          $scope.ecdapp.isRequestFailed = true;
+          $scope.ecdapp.errMsg = jsonObj.error;
+          $scope.ecdapp.tableData = [];
+        } else {
+          var tenants = [];
+          for (var tenIndx = 0; tenIndx < jsonObj.items.length; tenIndx++) {
+            tenants.push(jsonObj.items[tenIndx].name);
           }
+          localStorageService.set('tenants', JSON.stringify(tenants));
+          $scope.ecdapp.availableTenants = JSON.parse(localStorageService.get('tenants'));
+        }     
+      }, function(error) {
+        $log.error("blueprintController.getTenants failed: " + error);
+        $scope.ecdapp.isRequestFailed = true;
+        $scope.ecdapp.errMsg = error;
+      });
+  };  
+  
+  $scope.ecdapp.getOwnersList = function() {
+    $scope.ecdapp.bpOwners = JSON.parse(localStorageService.get('bpOwners'));
+    if ($scope.ecdapp.bpOwners == null) {
+    InventoryBlueprintService.getOwnersList().then(
+        function(jsonObj) {
+          if (jsonObj.error) {
+            $log.error("bpCtlr.getOwnersList failed: "
+                + jsonObj.error);
+            $scope.ecdapp.bpOwners = [];
+          } else {
+            $scope.ecdapp.bpOwners = jsonObj;
+            localStorageService.set('bpOwners', JSON.stringify(jsonObj));
+          }
+        },
+        function(error) {
+          $log.error("inventoryDeploymentController.getOwnersList failed: "
+              + error);
+          $scope.ecdapp.bpOwners = [];
+        });
+    }
+  };
+  
+    $scope.ecdapp.getBlueprintsList = function() {
+      $scope.ecdapp.availableBp = JSON.parse(localStorageService.get('bpNames'));
+      if ($scope.ecdapp.availableBp == null) {
+        InventoryBlueprintService.getBlueprintsList().then(
+          function(jsonObj) {
+            if (jsonObj.error) {
+              $log.error("execViewCtlr.getBlueprintsList failed: "
+                  + jsonObj.error);
+              $scope.ecdapp.availableBp = [];
+            } else {
+              $scope.ecdapp.availableBp = jsonObj.items;
+              localStorageService.set('bpNames', JSON.stringify(jsonObj.items));
+              //$scope.ecdapp.availableBp = JSON.parse(localStorageService.get('bpNames'));
+            }
+          },
+          function(error) {
+            $log.error("inventoryDeploymentController.getDeploymentList failed: "
+                + error);
+            $scope.ecdapp.availableBp = [];
+          });
+      }
+    };
+     
+  /**
+   * Get the components from database
+   * 
+   */
+  $scope.ecdapp.getAppComponents = function() {
+  InventoryBlueprintService.getComponents()
+  .then(function(jsonObj) {
+    if (jsonObj.error) {
+      $log.error("inventoryBlueprintController.loadComponents failed: " + jsonObj.error);
+      $scope.ecdapp.components = [];
+    } else {
+      if (debug)
+        $log.debug("inventoryBlueprintController.loadComponents succeeded, size " + jsonObj.data.length);
+      $scope.ecdapp.isRequestFailed = false;
+      $scope.ecdapp.errMsg = null;
+      $scope.ecdapp.components = jsonObj;
+      if (Array.isArray($scope.ecdapp.components) ) {
+        angular.forEach($scope.ecdapp.components, function(item, index) {
+          angular.forEach(item, function(value, key) {
+            if (key === "app") {
+              $scope.ecdapp.apps.push(value); 
+            } else {
+              angular.forEach(value, function(item, index) {
+                angular.forEach(item, function(value, key) {
+                  if (key === "cname") {
+                    if (!$scope.ecdapp.availableComp.includes(value)) {
+                      $scope.ecdapp.availableComp.push(value);
+                    }
+                  }
+                });
+              });    
+            }  
+          });
+        });
+      }
+    }     
+    $scope.ecdapp.isDataLoading = false;
+  }, function(error) {
+    $log.error("inventoryBlueprintController.loadComponents failed: " + error);
+    $scope.ecdapp.components = [];
+  });
+  };
+  
+  /**
+   * Loads the table. Interprets the remote controller's response and copies 
+   * to scope variables. The response is either list to be assigned to 
+   * tableData, or an error to be shown.
+   */
+  $scope.ecdapp.loadTable = function(sortBy, searchBy) {
+    $scope.ecdapp.isDataLoading = true;    
+    $scope.ecdapp.sortBy = sortBy;
+    //$scope.ecdapp.searchBy = searchBy;
+    InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, $scope.ecdapp.searchBy)
+    .then(function(jsonObj) {
+      if (jsonObj.error) {
+        $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error);
+        $scope.ecdapp.isRequestFailed = true;
+        $scope.ecdapp.errMsg = jsonObj.error;
+        $scope.ecdapp.tableData = [];
+      } else {
+        //if (debug)
+        //$log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); 
+        $scope.ecdapp.isRequestFailed = false;
+        $scope.ecdapp.errMsg = null;
+        $scope.ecdapp.totalPages = jsonObj.totalPages;
+        $scope.ecdapp.tableData = jsonObj.items;
+        //$scope.ecdapp.updateTable();
+        $scope.ecdapp.getBlueprintsList();
+        $scope.ecdapp.getOwnersList();
+      }                        
+      $scope.ecdapp.isDataLoading = false;
+    }, function(error) {
+      $log.error("inventoryBlueprintController.loadTable failed: " + error);
+      $scope.ecdapp.isRequestFailed = true;
+      $scope.ecdapp.errMsg = error;
+      $scope.ecdapp.tableData = [];
+      $scope.ecdapp.isDataLoading = false;
+      var loc = location.pathname;
+      var loc1 = loc.replace("/", "");
+      var loc2 = loc1.replace("/ecd", "/login.htm");
+      alert("Session expired - Sign in again");
+      location.replace("/"+loc2);
+    });
+  };
+
+  stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 300000, 100, false);
+
+  $scope.ecdapp.stopLoading = function() {
+    if (angular.isDefined(stop)) {
+      $interval.cancel(stop);
+      stop = undefined;
+    }
+  };
+
+  /**
+   * Loads the table. Interprets the remote controller's response and copies 
+   * to scope variables. The response is either list to be assigned to 
+   * tableData, or an error to be shown.
+   */
+  $scope.ecdapp.sortTable = function(sortBy) {
+    $scope.ecdapp.isDataLoading = true;
+    $scope.ecdapp.sortBy = sortBy;
+    InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage, sortBy, $scope.ecdapp.searchBy)
+    .then(function(jsonObj) {
+      if (jsonObj.error) {
+        $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error);
+        $scope.ecdapp.isRequestFailed = true;
+        $scope.ecdapp.errMsg = jsonObj.error;
+        $scope.ecdapp.tableData = [];
+      } else {
+        if (debug)
+          $log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); 
+        $scope.ecdapp.isRequestFailed = false;
+        $scope.ecdapp.errMsg = null;
+        $scope.ecdapp.totalPages = jsonObj.totalPages;
+        $scope.ecdapp.tableData = jsonObj.items;
+        //$scope.ecdapp.updateTable();
+      }                        
+      $scope.ecdapp.isDataLoading = false;
+    }, function(error) {
+      $log.error("inventoryBlueprintController.loadTable failed: " + error);
+      $scope.ecdapp.isRequestFailed = true;
+      $scope.ecdapp.errMsg = error;
+      $scope.ecdapp.tableData = [];
+      $scope.ecdapp.isDataLoading = false;
+    });
+  };
 
-          line.slice(0, line.Length - 1);
+  $scope.ecdapp.filterBySvc = function() {
+    if ( typeof $scope.ecdapp.searchString != "undefined" && 
+        $scope.ecdapp.searchString != '') {
+      if ($scope.ecdapp.searchString.includes("serviceRef:") ||
+          $scope.ecdapp.searchString.includes("app:") ||
+          $scope.ecdapp.searchString.includes("comp:")) {
+        if ($scope.ecdapp.filterByUser) {
+          $scope.ecdapp.searchBy = $scope.ecdapp.searchString + ";" + "owner:" + $scope.userId + ";" + ";";
+        } else {
+          $scope.ecdapp.searchBy = $scope.ecdapp.searchString;
+        }
+      } else {
+        if ($scope.ecdapp.filterByUser) {
+          $scope.ecdapp.searchBy = 'contains:' + $scope.ecdapp.searchString + ";" + "owner:" + $scope.userId + ";";
+        } else {
+          $scope.ecdapp.searchBy = 'contains:' + $scope.ecdapp.searchString;
+        }
+      }
+      $scope.ecdapp.searchTable();
+    }
+  };
 
-          str += line + '\r\n';
+  $scope.ecdapp.extendedfilterSrch = function() {
+    if ( typeof $scope.ecdapp.selectedBp != "undefined" && 
+        $scope.ecdapp.selectedBp != '') {
+      var svcFilterStr = 'serviceRef:' + $scope.ecdapp.selectedBp.toString();
+      $scope.ecdapp.searchBy = svcFilterStr + ';'
+      if ( typeof $scope.ecdapp.selectedApp != "undefined" && 
+          $scope.ecdapp.selectedApp != '') {
+        var appFilterStr = 'app:' + $scope.ecdapp.selectedApp.toString();
+        $scope.ecdapp.searchBy +=  appFilterStr + ';'
+      }
+      if ( typeof $scope.ecdapp.selectedComp != "undefined" &&
+          $scope.ecdapp.selectedComp != '') {
+        var compFilterStr = 'comp:' + $scope.ecdapp.selectedComp.toString();
+        $scope.ecdapp.searchBy +=  compFilterStr + ';'
       } 
+      if ( typeof $scope.ecdapp.selectedOwner != "undefined" &&
+          $scope.ecdapp.selectedOwner != '') {
+        var ownerFilterStr = 'owner:' + $scope.ecdapp.selectedOwner.toString();
+        $scope.ecdapp.searchBy +=  ownerFilterStr + ';'
+      }
+    } else {
+      if ( typeof $scope.ecdapp.selectedApp != "undefined" && 
+          $scope.ecdapp.selectedApp != '') {
+        var appFilterStr = 'app:' + $scope.ecdapp.selectedApp.toString();
+        $scope.ecdapp.searchBy =  appFilterStr + ';'
+        if ( typeof $scope.ecdapp.selectedComp != "undefined" &&
+            $scope.ecdapp.selectedComp != '' ) {
+          var compFilterStr = 'comp:' + $scope.ecdapp.selectedComp.toString();
+          $scope.ecdapp.searchBy +=  compFilterStr + ';'
+        }
+        if ( typeof $scope.ecdapp.selectedOwner != "undefined" &&
+            $scope.ecdapp.selectedOwner != '') {
+          var ownerFilterStr = 'owner:' + $scope.ecdapp.selectedOwner.toString();
+          $scope.ecdapp.searchBy +=  ownerFilterStr + ';'
+        }
+      } else {
+        if ( typeof $scope.ecdapp.selectedComp != "undefined" &&
+            $scope.ecdapp.selectedComp != '') {
+          var compFilterStr = 'comp:' + $scope.ecdapp.selectedComp.toString();
+          $scope.ecdapp.searchBy =  compFilterStr + ';'
+          if ( typeof $scope.ecdapp.selectedOwner != "undefined" &&
+              $scope.ecdapp.selectedOwner != '') {
+            var ownerFilterStr = 'owner:' + $scope.ecdapp.selectedOwner.toString();
+            $scope.ecdapp.searchBy +=  ownerFilterStr + ';'
+          }
+        } else {
+          if ( typeof $scope.ecdapp.selectedOwner != "undefined" &&
+              $scope.ecdapp.selectedOwner != '') {
+            var ownerFilterStr = 'owner:' + $scope.ecdapp.selectedOwner.toString();
+            $scope.ecdapp.searchBy =  ownerFilterStr + ';'
+          }
+        }
+
+      }     
+    }
+    if ($scope.ecdapp.filterByUser) {
+      $scope.ecdapp.searchBy += "owner:" + $scope.userId + ";";
+    }
+    $scope.ecdapp.searchString = $scope.ecdapp.searchBy;
+    $scope.ecdapp.searchTable();
+  };
+  
+  /**
+   * Loads the table. Interprets the remote controller's response and copies 
+   * to scope variables. The response is either list to be assigned to 
+   * tableData, or an error to be shown.
+   */
+  $scope.ecdapp.searchTable = function() {
+    $scope.ecdapp.isDataLoading = true;
+    $scope.ecdapp.showingMoreFilters = false;
+    if ($scope.ecdapp.currentPage != 1) {
+      $scope.ecdapp.currentPage = 1;
+    } else {
+      InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPage, $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, $scope.ecdapp.searchBy)
+      .then(function(jsonObj) {
+        if (jsonObj.error) {
+          $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error);
+          $scope.ecdapp.isRequestFailed = true;
+          $scope.ecdapp.errMsg = jsonObj.error;
+          $scope.ecdapp.tableData = [];
+        } else {
+          if (debug)
+            $log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); 
+          $scope.ecdapp.isRequestFailed = false;
+          $scope.ecdapp.errMsg = null;
+          $scope.ecdapp.totalPages = jsonObj.totalPages;
+          $scope.ecdapp.tableData = jsonObj.items;
+          //$scope.ecdapp.updateTable();
+        }                      
+        $scope.ecdapp.isDataLoading = false;
+      }, function(error) {
+        $log.error("inventoryBlueprintController.loadTable failed: " + error);
+        $scope.ecdapp.isRequestFailed = true;
+        $scope.ecdapp.errMsg = error;
+        $scope.ecdapp.tableData = [];
+        $scope.ecdapp.isDataLoading = false;
+        var loc = location.pathname;
+        var loc1 = loc.replace("/", "");
+        var loc2 = loc1.replace("/ecd", "/login.htm");
+        alert("Session expired - Sign in again");
+        location.replace("/"+loc2);
+      });
+    }
+  };
+
+  $scope.ecdapp.resetFilters = function() {
+    $scope.ecdapp.selectedBp = '';
+    $scope.ecdapp.selectedApp = '';
+    $scope.ecdapp.selectedComp = '';
+    $scope.ecdapp.selectedOwner = '';
+    $scope.ecdapp.searchString = '';
+  };
+  
+  $scope.ecdapp.reloadTable = function() {
+    $scope.ecdapp.currentPage = 1;
+    if ($scope.ecdapp.filterByUser) {
+      $scope.ecdapp.searchBy = "owner:" + $scope.userId + ";";
+    } else {
+      $scope.ecdapp.searchBy = '';
+    } 
+    $scope.ecdapp.searchString = '';
+    $scope.ecdapp.resetFilters();
+    $scope.ecdapp.loadTable();
+  };
+  
+  $scope.ecdapp.toggleUserFilt = function() {
+    $scope.ecdapp.reloadTable();
+    /*
+    if ($scope.ecdapp.filterByUser === false) {
+      $scope.ecdapp.searchString = '';
+    }
+    */
+  }
+  /**
+   * Invoked at first page load AND when
+   * user clicks on the B2B pagination control. 
+   */
+  $scope.pageChangeHandler = function(page) {
+    $scope.ecdapp.currentPage = page;
+    $scope.ecdapp.loadTable($scope.ecdapp.sortBy, $scope.ecdapp.searchBy);
+  }
+
+  /**
+   * Shows a modal pop-up to update a blueprint.
+   * Passes data in via an object named "message". 
+   * On success, updates the table.
+   */
+  $scope.ecdapp.updateBlueprintModalPopup = function(blueprint) {
+    $scope.ecdapp.editBlueprint = null;
+    var modalInstance = $modal.open({
+      templateUrl : 'inventory_blueprint_update_popup.html',
+      controller : 'inventoryBlueprintUpdateCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve : {
+        message : function() {
+          var dataForPopup = {
+              blueprint : blueprint
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+
+      if (debug)
+        $log.debug('updateBlueprintModalPopup: response: ' + JSON.stringify(response));
+      if (response == null) {
+        if (debug)
+          $log.debug('user closed dialog');
+      }
+      else {
+        if (response.error != null) {
+          $log.error('updateBlueprintModalPopup failed: ' + response.error);
+          alert('Failed to update blueprint:\n' + response.error);
+        }
+        else {
+          // success, get the updated list.
+          $scope.ecdapp.loadTable()
+        }
+      }
+    });
+  };
+
+  /**
+   * Shows a modal pop-up with blueprint content.
+   * Passes data in via an object named "message". 
+   */
+  $scope.ecdapp.viewBlueprintModalPopup = function(blueprint) {
+    $scope.ecdapp.editBlueprint = null;
+    var modalInstance = $modal.open({
+      templateUrl : 'inventory_blueprint_view_popup.html',
+      controller : 'inventoryBlueprintViewCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve : {
+        message : function() {
+          var dataForPopup = {
+              blueprint : blueprint
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+      // No response.
+    });
+  };
 
-               var uri = 'data:text/csv;charset=utf-8,' + escape(str);
-               var fileName = 'exported';
-               
-               var link = document.createElement("a");
-               link.href= uri;
-               
-               link.style = "visibility:hidden";
-               link.download = fileName + ".csv";
-               
-               document.body.appendChild(link);
-               link.click();
-               document.body.removeChild(link);
-       };
-       
-       $scope.ecdapp.createcsv = function(blueprint)
-       {
-               var bpArr =[];
-               bpArr.push(blueprint);
-               $scope.ecdapp.JSONToCSVConverter(bpArr);
-       };
-       
-       $scope.ecdapp.exportJson = function(blueprint)
-       {
-               var bpExportObj = {};
-               bpExportObj.application = blueprint.application;
-               bpExportObj.component = blueprint.component;
-               bpExportObj.typeName = blueprint.typeName;
-               bpExportObj.typeVersion = blueprint.typeVersion;
-               bpExportObj.blueprintTemplate = blueprint.blueprintTemplate;
-
-               var bpStr = JSON.stringify(bpExportObj);
-               var uri = 'data:text/json;charset=utf-8,' + escape(bpStr);
-               var fileName = blueprint.application + '_' + blueprint.component + 
-                       '_' + blueprint.typeName + '_' + blueprint.typeVersion;
-               
-               var link = document.createElement("a");
-               link.href= uri;
-               
-               link.style = "visibility:hidden";
-               link.download = fileName + ".json";
-               
-               document.body.appendChild(link);
-               link.click();
-               document.body.removeChild(link);
-       };
-       /**
-        * Loads the table. Interprets the remote controller's response and copies 
-        * to scope variables. The response is either list to be assigned to 
-        * tableData, or an error to be shown.
-        */
-       $scope.ecdapp.loadTable = function(sortBy, searchBy) {
-               $scope.ecdapp.isDataLoading = true;
-               $scope.ecdapp.sortBy = sortBy;
-               $scope.ecdapp.searchBy = searchBy;
-               InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPageNum, $scope.ecdapp.viewPerPage, sortBy, searchBy)
-                       .then(function(jsonObj) {
-                       if (jsonObj.error) {
-                               $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error);
-                               $scope.ecdapp.isRequestFailed = true;
-                               $scope.ecdapp.errMsg = jsonObj.error;
-                               $scope.ecdapp.tableData = [];
-                       } else {
-                               //if (debug)
-                                       //$log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); 
-                               $scope.ecdapp.isRequestFailed = false;
-                               $scope.ecdapp.errMsg = null;
-                               $scope.ecdapp.totalPages = jsonObj.totalPages;
-                               $scope.ecdapp.tableData = jsonObj.items;
-                               $scope.ecdapp.updateTable();
-                       }                       
-                       $scope.ecdapp.isDataLoading = false;
-               }, function(error) {
-                       $log.error("inventoryBlueprintController.loadTable failed: " + error);
-                       $scope.ecdapp.isRequestFailed = true;
-                       $scope.ecdapp.errMsg = error;
-                       $scope.ecdapp.tableData = [];
-                       $scope.ecdapp.isDataLoading = false;
-               });
-       };
-       
-       /**
-        * Loads the table. Interprets the remote controller's response and copies 
-        * to scope variables. The response is either list to be assigned to 
-        * tableData, or an error to be shown.
-        */
-       $scope.ecdapp.sortTable = function(sortBy) {
-               $scope.ecdapp.isDataLoading = true;
-               $scope.ecdapp.sortBy = sortBy;
-               InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPageNum, $scope.ecdapp.viewPerPage, sortBy, $scope.ecdapp.searchBy)
-                       .then(function(jsonObj) {
-                       if (jsonObj.error) {
-                               $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error);
-                               $scope.ecdapp.isRequestFailed = true;
-                               $scope.ecdapp.errMsg = jsonObj.error;
-                               $scope.ecdapp.tableData = [];
-                       } else {
-                               if (debug)
-                                       $log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); 
-                               $scope.ecdapp.isRequestFailed = false;
-                               $scope.ecdapp.errMsg = null;
-                               $scope.ecdapp.totalPages = jsonObj.totalPages;
-                               $scope.ecdapp.tableData = jsonObj.items;
-                               $scope.ecdapp.updateTable();
-                       }                       
-                       $scope.ecdapp.isDataLoading = false;
-               }, function(error) {
-                       $log.error("inventoryBlueprintController.loadTable failed: " + error);
-                       $scope.ecdapp.isRequestFailed = true;
-                       $scope.ecdapp.errMsg = error;
-                       $scope.ecdapp.tableData = [];
-                       $scope.ecdapp.isDataLoading = false;
-               });
-       };
-       
-       /**
-        * Loads the table. Interprets the remote controller's response and copies 
-        * to scope variables. The response is either list to be assigned to 
-        * tableData, or an error to be shown.
-        */
-       $scope.ecdapp.searchTable = function(searchBy) {
-               $scope.ecdapp.isDataLoading = true;
-               $scope.ecdapp.searchBy = searchBy;
-               InventoryBlueprintService.getBlueprints($scope.ecdapp.currentPageNum, $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, searchBy)
-                       .then(function(jsonObj) {
-                       if (jsonObj.error) {
-                               $log.error("inventoryBlueprintController.loadTable failed: " + jsonObj.error);
-                               $scope.ecdapp.isRequestFailed = true;
-                               $scope.ecdapp.errMsg = jsonObj.error;
-                               $scope.ecdapp.tableData = [];
-                       } else {
-                               if (debug)
-                                       $log.debug("inventoryBlueprintController.loadTable succeeded, size " + jsonObj.data.length); 
-                               $scope.ecdapp.isRequestFailed = false;
-                               $scope.ecdapp.errMsg = null;
-                               $scope.ecdapp.totalPages = jsonObj.totalPages;
-                               $scope.ecdapp.tableData = jsonObj.items;
-                               $scope.ecdapp.updateTable();
-                       }                       
-                       $scope.ecdapp.isDataLoading = false;
-               }, function(error) {
-                       $log.error("inventoryBlueprintController.loadTable failed: " + error);
-                       $scope.ecdapp.isRequestFailed = true;
-                       $scope.ecdapp.errMsg = error;
-                       $scope.ecdapp.tableData = [];
-                       $scope.ecdapp.isDataLoading = false;
-               });
-       };
-       
-       /**
-        * Invoked at first page load AND when
-        * user clicks on the B2B pagination control. 
-        */
-       $scope.pageChangeHandler = function(page) {
-               // console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page);
-               $scope.ecdapp.currentPageNum = page;
-               $scope.ecdapp.loadTable($scope.ecdapp.sortBy, $scope.ecdapp.searchBy);
-       }
-               
-       /**
-        * Shows a modal pop-up to update a blueprint.
-        * Passes data in via an object named "message". 
-        * On success, updates the table.
-        */
-       $scope.ecdapp.updateBlueprintModalPopup = function(blueprint) {
-               $scope.ecdapp.editBlueprint = null;
-               var modalInstance = $modal.open({
-                       templateUrl : 'inventory_blueprint_update_popup.html',
-                       controller : 'inventoryBlueprintUpdateCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-jumbo',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               blueprint : blueprint
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-
-                       if (debug)
-                               $log.debug('updateBlueprintModalPopup: response: ' + JSON.stringify(response));
-                       if (response == null) {
-                               if (debug)
-                                       $log.debug('user closed dialog');
-                       }
-                       else {
-                               if (response.error != null) {
-                                       $log.error('updateBlueprintModalPopup failed: ' + response.error);
-                                       alert('Failed to update blueprint:\n' + response.error);
-                               }
-                               else {
-                                       // success, get the updated list.
-                                       $scope.ecdapp.loadTable()
-                               }
-                       }
-               });
-       };
-       
-       /**
-        * Shows a modal pop-up with blueprint content.
-        * Passes data in via an object named "message". 
-        */
-       $scope.ecdapp.viewBlueprintModalPopup = function(blueprint) {
-               $scope.ecdapp.editBlueprint = null;
-               var modalInstance = $modal.open({
-                       templateUrl : 'inventory_blueprint_view_popup.html',
-                       controller : 'inventoryBlueprintViewCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-jumbo',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               blueprint : blueprint
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       // No response.
-               });
-       };
-       
-       /**
-        * Shows a modal pop-up to upload a blueprint. 
-        * Passes data in via an object named "message". 
-        * On success, updates the table.
-        */
-       $scope.ecdapp.uploadBlueprintModalPopup = function() {
-               $scope.ecdapp.editBlueprint = null;
-               var modalInstance = $modal.open({
-                       templateUrl : 'inventory_blueprint_upload_popup.html',
-                       controller : 'inventoryBlueprintUploadCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-jumbo',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               blueprint : $scope.ecdapp.editBlueprint,
-                                               blueprintList : $scope.ecdapp.tableData,
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       if (debug)
-                               $log.debug('uploadBlueprintModalPopup: response: ' + JSON.stringify(response));
-                       if (response == null) {
-                               if (debug)
-                                       $log.debug('user closed dialog');
-                       }
-                       else {
-                               if (response.error != null) {
-                                       $log.error('uploadBlueprintModalPopup failed: ' + response.error);
-                                       alert('Failed to upload blueprint:\n' + response.error);
-                               }
-                               else {
-                                       // success, get the updated list.
-                                       $scope.ecdapp.loadTable()
-                               }
-                       }
-               });
-       };
-       
-    /**
-        * Shows a modal pop-up to create a deployment from a blueprint. 
-        * Passes data in via an object named "message". 
-        */
-       $scope.ecdapp.deployBlueprintModalPopup = function(blueprint) {
-               var modalInstance = $modal.open({
-                       templateUrl : 'inventory_blueprint_deploy_popup.html',
-                       controller : 'inventoryBlueprintDeployCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-jumbo',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               blueprint : blueprint,
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       if (debug)
-                               $log.debug('deployBlueprintModalPopup: response: ' + JSON.stringify(response));
-                       if (response == null) {
-                               if (debug)
-                                       $log.debug('user closed dialog');
-                       }
-                       else {
-                               if (response.error != null) {
-                                       $log.error('deployBlueprintModalPopup failed: ' + response.error);
-                                       alert('Failed to deploy blueprint:\n' + response.error);
-                                       // No need to update THIS table.
-                                       // Must switch to deployments page to see result?  Awkward.
-                               }
-                       }
-               });
-       };
-
-       /**
-        * Shows a modal pop-up to confirm deletion. 
-        * On successful completion, updates the table.
-        */
-       $scope.ecdapp.deleteBlueprintModalPopup = function(blueprint) {
-               modalService.popupConfirmWin("Confirm", "Delete blueprint with name '"
-                               + blueprint.typeName + "'?", function() {
-                       InventoryBlueprintService.deleteBlueprint(blueprint.typeId).then(
-                                       function(response) {
-                                               if (debug)
-                                                       $log.debug('deleteBlueprintModalPopup: response: ' + JSON.stringify(response));
-                                               if (response && response.error) {
-                                                       // $log.error('deleteBlueprint failed: ' + response.error);
-                                                       alert('Failed to delete blueprint:\n' + response.error);
-                                               }
-                                               else {
-                                                       // No response body on success.
-                                                       $scope.ecdapp.loadTable();
-                                               }
-                                       },
-                                       function(error) {
-                                               $log.error('InventoryBlueprintService.deleteBlueprint failed: ' + error);
-                                               alert('Service failed to delete blueprint:\n' + error);
-                                       });
-               })
-       };
+  /**
+   * Shows a modal pop-up to upload a blueprint. 
+   * Passes data in via an object named "message". 
+   * On success, updates the table.
+   */
+  $scope.ecdapp.uploadBlueprintModalPopup = function() {
+    $scope.ecdapp.editBlueprint = null;
+    var modalInstance = $modal.open({
+      templateUrl : 'inventory_blueprint_upload_popup.html',
+      controller : 'inventoryBlueprintUploadCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve : {
+        message : function() {
+          var dataForPopup = {
+              apps : $scope.ecdapp.apps,
+              appComps: $scope.ecdapp.components
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+      if (debug)
+        $log.debug('uploadBlueprintModalPopup: response: ' + JSON.stringify(response));
+      if (response == null) {
+        if (debug)
+          $log.debug('user closed dialog');
+      }
+      else {
+        if (response.error != null) {
+          $log.error('uploadBlueprintModalPopup failed: ' + response.error);
+          alert('Failed to upload blueprint:\n' + response.error);
+        }
+        else {
+          // success, get the updated list.
+          $scope.ecdapp.loadTable()
+        }
+      }
+    });
+  };
+
+  /**
+   * Shows a modal pop-up to create a deployment from a blueprint. 
+   * Passes data in via an object named "message". 
+   */
+  $scope.ecdapp.deployBlueprintModalPopup = function(blueprint) {
+    var modalInstance = $modal.open({
+      templateUrl : 'inventory_blueprint_deploy_popup.html',
+      controller : 'inventoryBlueprintDeployCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve : {
+        message : function() {
+          var dataForPopup = {
+              blueprint : blueprint,
+              tenantList : $scope.ecdapp.availableTenants
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+      if (debug)
+        $log.debug('deployBlueprintModalPopup: response: ' + JSON.stringify(response));
+      if (response == null) {
+        if (debug)
+          $log.debug('user closed dialog');
+      }
+      else {
+        if (response.error != null) {
+          $log.error('deployBlueprintModalPopup failed: ' + response.error);
+          alert('Failed to deploy blueprint:\n' + response.error);
+          // No need to update THIS table.
+          // Must switch to deployments page to see result?  Awkward.
+        }
+      }
+    });
+  };
 
+  /**
+   * Shows a modal pop-up to confirm deletion. 
+   * On successful completion, updates the table.
+   */
+  $scope.ecdapp.deleteBlueprintModalPopup = function(blueprint) {
+    modalService.popupConfirmWin("Confirm", "Delete blueprint with name '"
+        + blueprint.typeName + "'?", function() {
+      InventoryBlueprintService.deleteBlueprint(blueprint.typeId).then(
+          function(response) {
+            if (debug)
+              $log.debug('deleteBlueprintModalPopup: response: ' + JSON.stringify(response));
+            if (response && response.error) {
+              // $log.error('deleteBlueprint failed: ' + response.error);
+              alert('Failed to delete blueprint:\n' + response.error);
+            }
+            else {
+              // No response body on success.
+              $scope.ecdapp.loadTable();
+            }
+          },
+          function(error) {
+            $log.error('InventoryBlueprintService.deleteBlueprint failed: ' + error);
+            alert('Service failed to delete blueprint:\n' + error);
+          });
+    })
+  };
+
+  $scope.ecdapp.getTenants();
+  
+  $scope.$on('$destroy', function() {
+    // Make sure that the interval is destroyed too
+    $scope.ecdapp.stopLoading();
+  });
+  
 });
 /*************************************************************************/
 
 appDS2.controller('inventoryBlueprintUpdateCtrl', function(
-               $scope, $log, $modalInstance, message, InventoryBlueprintService) {
-
-       'use strict';
-       
-       // Controls logging in this controller
-       var debug = false;
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'Update Blueprint';
-       $scope.ecdapp.updateInProgress = false;
-       // Create a ServiceTypeRequest object for edit
-       $scope.ecdapp.serviceType = angular.copy(message.blueprint);
-
-       /**
-        * Validates content of user-editable fields.
-        * Returns null if all is well, 
-        * a descriptive error message otherwise.
-        */
-       $scope.ecdapp.validateRequest = function(serviceType) {
-               if (serviceType == null)
-                       return 'No data found.\nPlease enter some values.';
-               if (serviceType.blueprintTemplate == null || serviceType.blueprintTemplate.trim() == '')
-                       return 'Blueprint Template is required.\nPlease enter a value.';
-               let blueprintTemplate = {};
-               try {
-                       blueprintTemplate = YAML.parse(serviceType.blueprintTemplate);
-               }
-               catch (ex) {
-                       return ('Blueprint template is not in YAML format:\n' + ex);
-               }
-               return null;
-       }
-       
-       $scope.ecdapp.updateBlueprint = function(serviceType) {
-               $scope.ecdapp.updateInProgress = true;
-               if (debug)
-                       $log.debug('updateBlueprint: serviceType is ' + JSON.stringify($scope.ecdapp.serviceType));
-               var validateMsg = $scope.ecdapp.validateRequest(serviceType);
-               if (validateMsg != null) {
-                       alert('Invalid Request:\n' + validateMsg);
-                       return;                 
-               }
-
-               InventoryBlueprintService.updateBlueprint(serviceType)
-                       .then(function(response) {
-                               if (debug)
-                                       $log.debug('inventoryBlueprintUpdateCtrl.updateBlueprint: ' + JSON.stringify(response));
-                               if (response && response.error) {
-                                       $log.error('InventoryBlueprintService.updateBlueprint failed: ' + response.error);
-                                       alert('Failed to update blueprint:\n' + response.error);
-                               }
-                               else {
-                                       // Delete service returns null on success.
-                                       $modalInstance.close("success");
-                               }
-                               $scope.ecdapp.updateInProgress = false;
-                       },
-                       function(error) {
-                               $log.error('InventoryBlueprintService.updateBlueprint failed: ' + error);
-                               $scope.ecdapp.updateInProgress = false;
-                               alert('Service failed to update blueprint:\n' + error);
-                       });
-
-       };
+    $scope, $log, $modalInstance, message, InventoryBlueprintService) {
+
+  'use strict';
+
+  // Controls logging in this controller
+  var debug = false;
+
+  // this object holds all app data and functions
+  $scope.ecdapp = {};
+  $scope.ecdapp.label = 'Update Blueprint';
+  $scope.ecdapp.updateInProgress = false;
+  // Create a ServiceTypeRequest object for edit
+  $scope.ecdapp.serviceTypeRequest = angular.copy(message.blueprint);
+
+  $scope.ecdapp.serviceType = 
+  {
+      asdcResourceId : '',
+      asdcServiceId : '',
+      asdcServiceURL : '',
+      blueprintTemplate : '',
+      owner : $scope.ecdapp.serviceTypeRequest.owner,
+      serviceIds : [],
+      serviceLocations : [],
+      typeName : $scope.ecdapp.serviceTypeRequest.typeName,
+      typeVersion : $scope.ecdapp.serviceTypeRequest.typeVersion,
+      vnfTypes : [],
+      application: $scope.ecdapp.serviceTypeRequest.application,
+      component: $scope.ecdapp.serviceTypeRequest.component
+  };
+  
+  // Fetch the blueprint
+  $scope.ecdapp.isDataLoading = true;
+  InventoryBlueprintService.viewBlueprint(message.blueprint.typeId).then(function(jsonObj) {
+    if (debug)
+      $log.debug("inventoryBlueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj));
+    if (jsonObj.error) {
+      $scope.ecdapp.errMsg = 'Request Failed';
+    }
+    else {
+      $scope.ecdapp.serviceType.blueprintTemplate = jsonObj.blueprintTemplate;
+    }
+    $scope.ecdapp.isDataLoading = false;
+  }, function(error) {
+    $scope.ecdapp.isDataLoading = false;
+    $log.error("blueprintViewCtrl failed: " + error);
+  });
+  
+  /**
+   * Validates content of user-editable fields.
+   * Returns null if all is well, 
+   * a descriptive error message otherwise.
+   */
+  $scope.ecdapp.validateRequest = function(serviceType) {
+    if (serviceType == null)
+      return 'No data found.\nPlease enter some values.';
+    if (serviceType.blueprintTemplate == null || serviceType.blueprintTemplate.trim() == '')
+      return 'Blueprint Template is required.\nPlease enter a value.';
+    let blueprintTemplate = {};
+    try {
+      blueprintTemplate = YAML.parse(serviceType.blueprintTemplate);
+    }
+    catch (ex) {
+      return ('Blueprint template is not in YAML format:\n' + ex);
+    }
+    return null;
+  }
+
+  $scope.ecdapp.updateBlueprint = function(serviceType) {
+    $scope.ecdapp.updateInProgress = true;
+    if (debug)
+      $log.debug('updateBlueprint: serviceType is ' + JSON.stringify($scope.ecdapp.serviceType));
+    var validateMsg = $scope.ecdapp.validateRequest(serviceType);
+    if (validateMsg != null) {
+      alert('Invalid Request:\n' + validateMsg);
+      return;                  
+    }
+
+    InventoryBlueprintService.updateBlueprint(serviceType)
+    .then(function(response) {
+      if (debug)
+        $log.debug('inventoryBlueprintUpdateCtrl.updateBlueprint: ' + JSON.stringify(response));
+      if (response && response.error) {
+        $log.error('InventoryBlueprintService.updateBlueprint failed: ' + response.error);
+        alert('Failed to update blueprint:\n' + response.error);
+      }
+      else {
+        $modalInstance.close("success");
+      }
+      $scope.ecdapp.updateInProgress = false;
+    },
+    function(error) {
+      $log.error('InventoryBlueprintService.updateBlueprint failed: ' + error);
+      $scope.ecdapp.updateInProgress = false;
+      alert('Service failed to update blueprint:\n' + error);
+    });
+
+  };
 
 });
 
 
 appDS2.controller('inventoryBlueprintUploadCtrl', function(
-               $scope, $log, $modalInstance, message, InventoryBlueprintService) {
-
-       'use strict';
-       
-       // Controls logging in this controller
-       var debug = false;
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'Upload Blueprint';
-       $scope.ecdapp.uploadInProgress = false;
-       $scope.ecdapp.serviceTypeRequest = 
-               {
-                       asdcResourceId : '',
-                       asdcServiceId : '',
-                       asdcServiceURL : '',
-                       blueprintTemplate : '',
-                       owner : $scope.userId,
-                       serviceIds : '',
-                       serviceLocations : '',
-                       typeName : '',
-                       typeVersion : '',
-                       vnfTypes : '',
-                       application: '',
-                       component: ''
-               };
-       $scope.ecdapp.writeRole = false;
-       $scope.ecdapp.newCompName = "";
-       $scope.ecdapp.newCompDisplayName = "";
-       $scope.ecdapp.newCompId = null;
-       $scope.ecdapp.enableAppForm = false;
-       $scope.ecdapp.apps = [];
-       $scope.ecdapp.comps = [];
-       $scope.ecdapp.validAppl = false;
-       $scope.ecdapp.validComp = false;
-       $scope.ecdapp.isImport = false;
-       
-       /**
-        * Handler for file-read event reads file, parses JSON, validates content.
-        */
-       var importFileReader = new FileReader();
-       importFileReader.onload = function(event) {
-               let jsonString = importFileReader.result;
-               if (debug)
-                       $log.debug('fileReader.onload: read: ' + jsonString);
-               let ydict = {};
-               try {
-                       ydict = JSON.parse(jsonString);
-               }
-               catch (ex) {
-                       alert('Failed to parse file as JSON:\n' + ex);
-               }
-               // Process the file
-               for (var ykey in ydict) {
-                       let yval = ydict[ykey];
-                       if (debug)
-                               $log.debug('importFileReader.onload: typeof ' + ykey + ' is ' + typeof ykey);
-                       
-                       if (ykey === "application") {
-                               $scope.ecdapp.serviceTypeRequest.application = yval;
-                               $scope.ecdapp.validAppl = true;
-                       } else if (ykey === "component") {
-                               $scope.ecdapp.serviceTypeRequest.component = yval;
-                               $scope.ecdapp.validComp = true;
-                       } else if (ykey === "typeName") {
-                               $scope.ecdapp.serviceTypeRequest.typeName = yval;
-                       } else if (ykey === "typeVersion") {
-                               $scope.ecdapp.serviceTypeRequest.typeVersion = yval;
-                       } else if (ykey === "blueprintTemplate") {
-                               $scope.ecdapp.serviceTypeRequest.blueprintTemplate = yval;
-                       }
-               }
-       }
-       
-       $scope.ecdapp.handleImportCb = function($event) {
-                 var checkbox = $event.target;
-                 var action = (checkbox.checked ? 'import' : 'regular');
-                 if (action === 'import') {
-                         $scope.ecdapp.serviceTypeRequest.application = '';
-                         $scope.ecdapp.serviceTypeRequest.component = '';
-                         $scope.ecdapp.isImport = true;
-                 }       
-                 if (action === 'regular') {
-                         $scope.ecdapp.serviceTypeRequest.application = 'Select Application';
-                         $scope.ecdapp.serviceTypeRequest.component = 'Select Component';
-                         $scope.ecdapp.isImport = false;
-                 }
-       }
-       // Handler for file-select event
-       $scope.ecdapp.handleImportFile = function() {
-               if (debug)
-                       $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.serviceTypeRequest.fileModel.name);
-               importFileReader.readAsText($scope.ecdapp.serviceTypeRequest.fileModel);
-       };
-       
-       /**
-        * Get the components from database
-        * 
-        */
-       InventoryBlueprintService.getComponents()
-               .then(function(jsonObj) {
-               if (jsonObj.error) {
-                       $log.error("inventoryBlueprintController.loadComponents failed: " + jsonObj.error);
-                       $scope.ecdapp.components = [];
-               } else {
-                       if (debug)
-                               $log.debug("inventoryBlueprintController.loadComponents succeeded, size " + jsonObj.data.length);
-                       $scope.ecdapp.isRequestFailed = false;
-                       $scope.ecdapp.errMsg = null;
-                       $scope.ecdapp.components = jsonObj;
-                       if (Array.isArray($scope.ecdapp.components) ) {
-                                 angular.forEach($scope.ecdapp.components, function(item, index) {
-                                         angular.forEach(item, function(value, key) {
-                                                 if (key === "app") {
-                                                         $scope.ecdapp.apps.push(value); 
-                                                 }       
-                                         });
-                         });
-                       }
-               }                       
-               $scope.ecdapp.isDataLoading = false;
-       }, function(error) {
-               $log.error("inventoryBlueprintController.loadComponents failed: " + error);
-               $scope.ecdapp.components = [];
-       });
-
-       //$scope.ecdapp.components = [{"ECOMPC":[{"compId":1,"cname":"controller","dname":"CONTROLLER"},{"compId":2,"cname":"mso","dname":"MSO"},{"compId":3,"cname":"appc","dname":"APP-C"},{"compId":4,"cname":"clamp","dname":"CLAMP"},{"compId":5,"cname":"ecompscheduler","dname":"ECOMP SCHEDULER"},{"compId":6,"cname":"policy","dname":"POLICY"},{"compId":7,"cname":"eipam","dname":"EIPAM"},{"compId":181,"cname":"pdasms","dname":"PDAS-MS"},{"cname":"true"}]},
-       //       {"DCAE": [{"compId":8,"cname":"dcae","dname":"DCAE"}]}];
-       $scope.ecdapp.selectAppComp = function(appName) {
-        if(appName === "Select Application"){
-            $scope.ecdapp.validAppl = false;
-        } else {
-               $scope.ecdapp.validAppl = true;
-                       for (var appIndx = 0; appIndx < $scope.ecdapp.components.length; appIndx++) {
-                               if ($scope.ecdapp.components[appIndx].app === appName) {
-                                       $scope.ecdapp.comps = $scope.ecdapp.components[appIndx].comps;
-                                       break;
-                               }
-                       }
-        }
-       }
-       $scope.ecdapp.validateComp = function(appName) {
-        if($scope.ecdapp.serviceTypeRequest.component === "Select Component"){
-            $scope.ecdapp.validComp = false;
-        } else {
-               $scope.ecdapp.validComp = true;
-        }
-       }
-       var fileReader = new FileReader();
-       fileReader.onload = function(event) {
-               let yamlString = fileReader.result;
-               $scope.ecdapp.serviceTypeRequest.blueprintTemplate = yamlString;
-       }
-       $scope.ecdapp.enableAddApp = function() {
-               if ($scope.ecdapp.enableAppForm) {
-                       $scope.ecdapp.enableAppForm = false;
-               } else {
-                       $scope.ecdapp.enableAppForm = true;
-               }
-       }
-       $scope.ecdapp.addApplication = function(appName, compId, compName, compDisplayName) {
-               // save new application to database, reload components list
-        if (compName.trim().length < 1 || compDisplayName.trim().length < 1) {
-            alert("Must enter value for Component name and display name");
-            return;
+    $scope, $log, $modalInstance, message, InventoryBlueprintService, localStorageService) {
+
+  'use strict';
+
+  // Controls logging in this controller
+  var debug = false;
+
+  // this object holds all app data and functions
+  $scope.ecdapp = {};
+  $scope.ecdapp.label = 'Upload Blueprint';
+  $scope.ecdapp.uploadInProgress = false;
+
+  $scope.ecdapp.serviceTypeRequest = 
+  {
+      asdcResourceId : '',
+      asdcServiceId : '',
+      asdcServiceURL : '',
+      blueprintTemplate : '',
+      owner : $scope.userId,
+      serviceIds : '',
+      serviceLocations : '',
+      typeName : '',
+      typeVersion : '',
+      vnfTypes : '',
+      application: '',
+      component: ''
+  };
+
+  if (!$scope.ecdapp.isInternal) {
+    $scope.ecdapp.serviceTypeRequest.application = 'DCAE';
+    $scope.ecdapp.serviceTypeRequest.component = 'dcae';
+  }
+  $scope.ecdapp.writeRole = false;
+  $scope.ecdapp.isImport = false;
+
+  /**
+   * Handler for file-read event reads file, parses JSON, validates content.
+   */
+  var importFileReader = new FileReader();
+  importFileReader.onload = function(event) {
+    let jsonString = importFileReader.result;
+    if (debug)
+      $log.debug('fileReader.onload: read: ' + jsonString);
+    let ydict = {};
+    try {
+      ydict = JSON.parse(jsonString);
+    }
+    catch (ex) {
+      alert('Failed to parse file as JSON:\n' + ex);
+    }
+    // Process the file
+    for (var ykey in ydict) {
+      let yval = ydict[ykey];
+      if (debug)
+        $log.debug('importFileReader.onload: typeof ' + ykey + ' is ' + typeof ykey);
+
+      if (ykey === "application") {
+        $scope.ecdapp.serviceTypeRequest.application = yval;
+        $scope.ecdapp.validAppl = true;
+      } else if (ykey === "component") {
+        $scope.ecdapp.serviceTypeRequest.component = yval;
+        $scope.ecdapp.validComp = true;
+      } else if (ykey === "typeName") {
+        $scope.ecdapp.serviceTypeRequest.typeName = yval;
+      } else if (ykey === "typeVersion") {
+        $scope.ecdapp.serviceTypeRequest.typeVersion = yval;
+      } else if (ykey === "blueprintTemplate") {
+        $scope.ecdapp.serviceTypeRequest.blueprintTemplate = yval;
+      }
+    }
+  }
+
+  $scope.ecdapp.handleImportCb = function($event) {
+    var checkbox = $event.target;
+    var action = (checkbox.checked ? 'import' : 'regular');
+    if (action === 'import' && $scope.ecdapp.isInternal) {
+      $scope.ecdapp.serviceTypeRequest.application = '';
+      $scope.ecdapp.serviceTypeRequest.component = '';
+      $scope.ecdapp.isImport = true;
+    }    
+    if (action === 'regular' && $scope.ecdapp.isInternal) {
+      $scope.ecdapp.serviceTypeRequest.application = 'Select Application';
+      $scope.ecdapp.serviceTypeRequest.component = 'Select Component';
+      $scope.ecdapp.isImport = false;
+    }
+  }
+  // Handler for file-select event
+  $scope.ecdapp.handleImportFile = function() {
+    if (debug)
+      $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.serviceTypeRequest.fileModel.name);
+    importFileReader.readAsText($scope.ecdapp.serviceTypeRequest.fileModel);
+  };
+
+
+  //$scope.ecdapp.components = [{"ECOMPC":[{"compId":1,"cname":"controller","dname":"CONTROLLER"},{"compId":2,"cname":"mso","dname":"MSO"},{"compId":3,"cname":"appc","dname":"APP-C"},{"compId":4,"cname":"clamp","dname":"CLAMP"},{"compId":5,"cname":"ecompscheduler","dname":"ECOMP SCHEDULER"},{"compId":6,"cname":"policy","dname":"POLICY"},{"compId":7,"cname":"eipam","dname":"EIPAM"},{"compId":181,"cname":"pdasms","dname":"PDAS-MS"},{"cname":"true"}]},
+  //    {"DCAE": [{"compId":8,"cname":"dcae","dname":"DCAE"}]}];
+  $scope.ecdapp.selectAppComp = function(appName) {
+    if(appName === "Select Application") {
+      $scope.ecdapp.validAppl = false;
+    } else {
+      $scope.ecdapp.comps = [];
+      $scope.ecdapp.serviceTypeRequest.component = "";
+      $scope.ecdapp.validAppl = true;
+      for (var appIndx = 0; appIndx < $scope.ecdapp.components.length; appIndx++) {
+        if ($scope.ecdapp.components[appIndx].app === appName) {
+          $scope.ecdapp.comps = $scope.ecdapp.components[appIndx].comps;
+          break;
         }
-               //console.log("Saving " + applicationName + " to components list");
-               InventoryBlueprintService.insertComponent(compName, compDisplayName.toUpperCase()).then(function(jsonObj) {
-            if (jsonObj.error) {
-                $log.error("inventoryBlueprintController.loadComponents failed: " + jsonObj.error);
-            } else {
-                if (debug)
-                    $log.debug("inventoryBlueprintController.loadComponents succeeded, size " + jsonObj.data.length);
-                //console.log(jsonObj);
-                InventoryBlueprintService.getComponents().then(function(jsonObj) {
-                       /*
-                    $scope.ecdapp.newApplicationName = "";
-                    $scope.ecdapp.newApplicationDisplayName = "";
-                    $scope.ecdapp.selectedOption = $scope.ecdapp.components[0];
-                    */
-                    $scope.ecdapp.components = jsonObj;
-                    $scope.ecdapp.enableAppForm = false;
-                    $scope.ecdapp.selectAppComp(appName);
-                               });
-            }
-               }, function(error) {
-            $log.error("inventoryBlueprintController.addApplication failed: " + error);
-        });
-       };
-
-       // Handler for file-select event
-       $scope.handleFileSelect = function() {
-               if (debug)
-                       $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.serviceTypeRequest.fileModel.name);
-               fileReader.readAsText($scope.ecdapp.serviceTypeRequest.fileModel);
-       };
-       // Convert serviceIds, serviceLocations, and vnfTypes to JSON Array
-       $scope.ecdapp.convertStringsToArrays = function(serviceTypeRequest) {
-               if (serviceTypeRequest.serviceIds || serviceTypeRequest.serviceIds.trim() != '') {
-                       try {
-                               serviceTypeRequest.serviceIds = angular.fromJson(serviceTypeRequest.serviceIds.split(","));
-                       } catch (error) {
-                               return 'Service Ids is not in the correct format.';
-                       }
-               } else {
-                       serviceTypeRequest.serviceIds = [];
-               }
-               
-               if (serviceTypeRequest.serviceLocations || serviceTypeRequest.serviceLocations.trim() != '') {
-                       try {
-                               serviceTypeRequest.serviceLocations = angular.fromJson(serviceTypeRequest.serviceLocations.split(","));
-                       } catch (error) {
-                               return 'Service Locations is not in the correct format.';
-                       }
-               } else {
-                       serviceTypeRequest.serviceLocations = [];
-               }
-               
-               if (serviceTypeRequest.vnfTypes || serviceTypeRequest.vnfTypes.trim() != '') {
-                       try {
-                               serviceTypeRequest.vnfTypes = angular.fromJson(serviceTypeRequest.vnfTypes.split(","));
-                       } catch (error) {
-                               return 'VNF Types is not in the correct format.';
-                       }
-               } else {
-                       serviceTypeRequest.vnfTypes = [];
-               }
-               
-               try {
-                       if (isNaN(serviceTypeRequest.typeVersion)) {
-                       serviceTypeRequest.typeVersion = serviceTypeRequest.typeVersion.replace(/\./gi, "");
-                       serviceTypeRequest.typeVersion = angular.fromJson(serviceTypeRequest.typeVersion);
-                       }
-               } catch (error) {
-                       return 'typeVersion is not in the correct format.';
-               }
-               
-               return null;
-       }
-       
-       /**
-        * Validates content of user-editable fields.
-        * Returns null if all is well, 
-        * a descriptive error message otherwise.
-        */
-       $scope.ecdapp.validateRequest = function(serviceTypeRequest) {
-               if (!serviceTypeRequest)
-                       return 'No data found.\nPlease enter some values.';
-               if (!serviceTypeRequest.owner || serviceTypeRequest.owner.trim() == '') {
-                       return 'Application/Owner is required.\nPlease enter a value.';
-               }
-               if (!serviceTypeRequest.typeName || serviceTypeRequest.typeName.trim() == '') {
-                       return 'Type Name is required.\nPlease enter a value.';
-               }
-               if (!serviceTypeRequest.typeVersion ) {
-                               //|| serviceTypeRequest.typeVersion.trim() == '') {
-                       return 'Type Version is required.\nPlease enter a value.';
-               }
-               if (!serviceTypeRequest.blueprintTemplate || serviceTypeRequest.blueprintTemplate.trim() == '')
-                       return 'Blueprint Template is required.\nPlease enter a value.';
-
-               return null;
-       }
-       
-       $scope.ecdapp.uploadBlueprint = function(serviceTypeRequest) {  
-               if (debug)
-                       $log.debug('uploadBlueprint: serviceType is ' + JSON.stringify(serviceTypeRequest));
-               $scope.ecdapp.uploadInProgress = true;
-               var validateMsg = $scope.ecdapp.validateRequest(serviceTypeRequest);
-               if (validateMsg != null) {
-                       editServiceType = angular.copy(serviceTypeRequest);
-                       alert('Invalid Request:\n' + validateMsg);
-                       $scope.ecdapp.uploadInProgress = false;
-                       return;                 
-               }
-               //var authUser = $scope.userId;
-               //serviceTypeRequest.owner = serviceTypeRequest.owner + ':' + authUser;
-               // Create a editServiceTypeRequest object for edit
-               var editServiceType = angular.copy(serviceTypeRequest);
-               var convertMsg = $scope.ecdapp.convertStringsToArrays(editServiceType);
-               if (convertMsg != null) {
-                       editServiceType = angular.copy(serviceTypeRequest);
-                       alert('Invalid Request:\n' + convertMsg);
-                       return;                 
-               }
-
-               InventoryBlueprintService.uploadBlueprint(editServiceType)
-                       .then(function(response) {
-                               if (debug)
-                                       $log.debug('inventoryBlueprintUploadCtrl.uploadBlueprint: ' + JSON.stringify(response));
-                               if (response && response.error) {
-                                       $log.error('InventoryBlueprintService.uploadBlueprint failed: ' + response.error);
-                                       alert('Failed to upload blueprint:\n' + response.error);
-                               }
-                               else {
-                                       // Upload service returns null on success.
-                                       $modalInstance.close("success");
-                               }
-                               $scope.ecdapp.uploadInProgress = false;
-                       },
-                       function(error) {
-                               $log.error('InventoryBlueprintService.uploadBlueprint failed: ' + error);
-                               $scope.ecdapp.uploadInProgress = false;
-                               alert('Service failed to upload blueprint:\n' + error);
-                       });
-
-       };
+      }
+    }
+  }
+  $scope.ecdapp.validateComp = function(appName) {
+    if($scope.ecdapp.serviceTypeRequest.component === "Select Component"){
+      $scope.ecdapp.validComp = false;
+    } else {
+      $scope.ecdapp.validComp = true;
+    }
+  }
+  var fileReader = new FileReader();
+  fileReader.onload = function(event) {
+    let yamlString = fileReader.result;
+    $scope.ecdapp.serviceTypeRequest.blueprintTemplate = yamlString;
+  }
+
+  // Handler for file-select event
+  $scope.handleFileSelect = function() {
+    if (debug)
+      $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.serviceTypeRequest.fileModel.name);
+    fileReader.readAsText($scope.ecdapp.serviceTypeRequest.fileModel);
+  };
+  // Convert serviceIds, serviceLocations, and vnfTypes to JSON Array
+
+  $scope.ecdapp.convertStringsToArrays = function(serviceTypeRequest) {
+    if (serviceTypeRequest.serviceIds || serviceTypeRequest.serviceIds.trim() != '') {
+      try {
+        serviceTypeRequest.serviceIds = angular.fromJson(serviceTypeRequest.serviceIds.split(","));
+      } catch (error) {
+        return 'Service Ids is not in the correct format.';
+      }
+    } else {
+      serviceTypeRequest.serviceIds = [];
+    }
+
+    if (serviceTypeRequest.serviceLocations || serviceTypeRequest.serviceLocations.trim() != '') {
+      try {
+        serviceTypeRequest.serviceLocations = angular.fromJson(serviceTypeRequest.serviceLocations.split(","));
+      } catch (error) {
+        return 'Service Locations is not in the correct format.';
+      }
+    } else {
+      serviceTypeRequest.serviceLocations = [];
+    }
+
+    if (serviceTypeRequest.vnfTypes || serviceTypeRequest.vnfTypes.trim() != '') {
+      try {
+        serviceTypeRequest.vnfTypes = angular.fromJson(serviceTypeRequest.vnfTypes.split(","));
+      } catch (error) {
+        return 'VNF Types is not in the correct format.';
+      }
+    } else {
+      serviceTypeRequest.vnfTypes = [];
+    }
+    return null;
+  }
+
+  $scope.ecdapp.isInt = function(value) {
+    return !isNaN(value) && 
+    parseInt(Number(value)) == value && 
+    !isNaN(parseInt(value, 10));
+  }
+  /**
+   * Validates content of user-editable fields.
+   * Returns null if all is well, 
+   * a descriptive error message otherwise.
+   */
+  $scope.ecdapp.validateRequest = function(serviceTypeRequest) {
+    if (!serviceTypeRequest)
+      return 'No data found.\nPlease enter some values.';
+    if (!serviceTypeRequest.owner || serviceTypeRequest.owner.trim() == '') {
+      return 'Application/Owner is required.\nPlease enter a value.';
+    }
+    if (!serviceTypeRequest.typeName || serviceTypeRequest.typeName.trim() == '') {
+      return 'Type Name is required.\nPlease enter a value.';
+    }
+    if (!serviceTypeRequest.typeVersion ) {
+      //|| serviceTypeRequest.typeVersion.trim() == '') {
+      return 'Type Version is required.\nPlease enter a value.';
+    }
+    if (!$scope.ecdapp.isInt(serviceTypeRequest.typeVersion) ) {
+      //|| serviceTypeRequest.typeVersion.trim() == '') {
+      return 'Type Version should be a valid Integer.';
+    }
+    if (!serviceTypeRequest.blueprintTemplate || serviceTypeRequest.blueprintTemplate.trim() == '')
+      return 'Blueprint Template is required.\nPlease enter a value.';
+
+    return null;
+  }
+
+  $scope.ecdapp.uploadBlueprint = function(serviceTypeRequest) {       
+    if (debug)
+      $log.debug('uploadBlueprint: serviceType is ' + JSON.stringify(serviceTypeRequest));
+    $scope.ecdapp.uploadInProgress = true;
+    var validateMsg = $scope.ecdapp.validateRequest(serviceTypeRequest);
+    if (validateMsg != null) {
+      editServiceType = angular.copy(serviceTypeRequest);
+      alert('Invalid Request:\n' + validateMsg);
+      $scope.ecdapp.uploadInProgress = false;
+      return;                  
+    }
+    //var authUser = $scope.userId;
+    //serviceTypeRequest.owner = serviceTypeRequest.owner + ':' + authUser;
+    // Create a editServiceTypeRequest object for edit
+    var editServiceType = angular.copy(serviceTypeRequest);
+    var convertMsg = $scope.ecdapp.convertStringsToArrays(editServiceType);
+    if (convertMsg != null) {
+      editServiceType = angular.copy(serviceTypeRequest);
+      alert('Invalid Request:\n' + convertMsg);
+      return;                  
+    }
+
+    InventoryBlueprintService.uploadBlueprint(editServiceType)
+    .then(function(response) {
+      if (debug)
+        $log.debug('inventoryBlueprintUploadCtrl.uploadBlueprint: ' + JSON.stringify(response));
+      if (response && response.error) {
+        $log.error('InventoryBlueprintService.uploadBlueprint failed: ' + response.error);
+        alert('Failed to upload blueprint:\n' + response.error);
+      }
+      else {
+        // Upload service returns null on success.
+        $modalInstance.close("success");
+      }
+      $scope.ecdapp.uploadInProgress = false;
+    },
+    function(error) {
+      $log.error('InventoryBlueprintService.uploadBlueprint failed: ' + error);
+      $scope.ecdapp.uploadInProgress = false;
+      alert('Service failed to upload blueprint:\n' + error);
+    });
+
+  };
 
 });
 
 /*************************************************************************/
 
 appDS2.controller('inventoryBlueprintViewCtrl', function(
-               $scope, $log, message, InventoryBlueprintService) {
-
-       'use strict';
-       
-       var debug = false;
-       
-       if (debug)
-               $log.debug("inventoryBlueprintViewCtrl.message: " + JSON.stringify(message));
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.blueprintId = message.blueprint.typeId;
-       
-       $scope.ecdapp.label = 'View Blueprint ' + message.blueprint.typeName;
-
-       // Fetch the blueprint
-       $scope.ecdapp.isDataLoading = true;
-       InventoryBlueprintService.viewBlueprint(message.blueprint.typeId).then(function(jsonObj) {
-               if (debug)
-                       $log.debug("inventoryBlueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj));
-               if (jsonObj.error) {
-                       $scope.ecdapp.errMsg = 'Request Failed';
-               }
-               else {
-                       $scope.ecdapp.blueprint = jsonObj.blueprintTemplate;
-               }
-               $scope.ecdapp.isDataLoading = false;
-       }, function(error) {
-               $scope.ecdapp.isDataLoading = false;
-               alert('Failed to get blueprint. Please retry.');
-               $log.error("blueprintViewCtrl failed: " + error);
-       });
-       
+    $scope, $log, message, InventoryBlueprintService) {
+
+  'use strict';
+
+  var debug = false;
+
+  if (debug)
+    $log.debug("inventoryBlueprintViewCtrl.message: " + JSON.stringify(message));
+
+  // this object holds all app data and functions
+  $scope.ecdapp = {};
+  $scope.ecdapp.blueprintId = message.blueprint.typeId;
+
+  $scope.ecdapp.label = 'View Blueprint ' + message.blueprint.typeName;
+
+  // Fetch the blueprint
+  $scope.ecdapp.isDataLoading = true;
+  InventoryBlueprintService.viewBlueprint(message.blueprint.typeId).then(function(jsonObj) {
+    if (debug)
+      $log.debug("inventoryBlueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj));
+    if (jsonObj.error) {
+      $scope.ecdapp.errMsg = 'Request Failed';
+    }
+    else {
+      $scope.ecdapp.blueprint = jsonObj.blueprintTemplate;
+    }
+    $scope.ecdapp.isDataLoading = false;
+  }, function(error) {
+    $scope.ecdapp.isDataLoading = false;
+    alert('Failed to get blueprint. Please retry.');
+    $log.error("blueprintViewCtrl failed: " + error);
+  });
+
 });
 
+appDS2.directive('json', function() {
+  return {
+    restrict: 'A', // only activate on element attribute
+    require: 'ngModel', // get a hold of NgModelController
+    link: function(scope, element, attrs, ngModelCtrl) {
+      function toUser(object) {
+        if (typeof object === 'object') {
+          return angular.toJson(object, true);
+        } else {
+          return object;
+        }
+      }              
+      ngModelCtrl.$formatters.push(toUser);
 
+      // $watch(attrs.ngModel) wouldn't work if this directive created a new scope;
+      // see http://stackoverflow.com/questions/14693052/watch-ngmodel-from-inside-directive-using-isolate-scope how to do it then
+      scope.$watch(attrs.ngModel, function(newValue, oldValue) {
+        if (newValue != oldValue) {
+          ngModelCtrl.$setViewValue(toUser(newValue));
+          // TODO avoid this causing the focus of the input to be lost..
+          ngModelCtrl.$render();
+        }
+      }, true); // MUST use objectEquality (true) here, for some reason..
+    }
+  };  
+});
 /*************************************************************************/
 
 appDS2.controller('inventoryBlueprintDeployCtrl', function(
-               $scope, $rootScope, $log, $modal, $modalInstance, message, InventoryDeploymentService, InventoryBlueprintService) {
-
-       'use strict';
-       
-       // Controls logging in this controller
-       var debug = false;
-       
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'Deploy Blueprint';
-       $scope.ecdapp.errMsg = '';
-       
-       // deployment in progress
-       $scope.ecdapp.deploymentInProgress = false;
-       $scope.ecdapp.isDataLoading = false;
-       $scope.ecdapp.tenant = $rootScope.tenantList.tenant;
-       $scope.ecdapp.validTenant = false;
-       
-       // Cache the input parameter names for validation
-       if (debug)
-               $log.debug('inventoryBlueprintDeployCtrl: inputs: ' + JSON.stringify(message.blueprint.blueprintInputs));
-       $scope.ecdapp.inputsDict = message.blueprint.blueprintInputs;
-
-       // Copy the input parameter names and default values
-       let inputsAndDefaults = {};
-       for (var pkey in message.blueprint.blueprintInputs) {
-               if (debug)
-                       $log.debug('inventoryBlueprintDeployCtrl: checking key ' + pkey);
-               let dval = message.blueprint.blueprintInputs[pkey].defaultValue;
-               if (  typeof dval === "undefined" )
-                       dval = '';
-               inputsAndDefaults[pkey] = dval;
-       }
-       if (debug)
-               $log.debug('inventoryBlueprintDeployCtrl: inputsAndDefaults: ' + JSON.stringify(inputsAndDefaults));
-       
-       // Create an object for edit
-       //var genDeployId = message.blueprint.component + "_" + message.blueprint.typeName;
-       $scope.ecdapp.editRequest = {
-               deployment_id : '',
-               type_id : message.blueprint.typeId,
-               fileModel : null,
-               parmFileDict : inputsAndDefaults,
-               tenant : '',
-               component: message.blueprint.component,
-               tag : message.blueprint.typeName
-       };
-    $scope.ecdapp.validateTenant = function(){
-        if($scope.ecdapp.editRequest.tenant === "Select Tenant"){
-            $scope.ecdapp.validTenant = false;
-        }else{
-               $scope.ecdapp.validTenant = true;
-        }
+    $scope, $rootScope, $log, $modal, $modalInstance, message, InventoryDeploymentService, InventoryBlueprintService) {
+
+  'use strict';
+
+  // Controls logging in this controller
+  var debug = false;
+
+  // this object holds all app data and functions
+  $scope.ecdapp = {};
+  $scope.ecdapp.label = 'Deploy Blueprint';
+  $scope.ecdapp.errMsg = '';
+  $scope.ecdapp.availableTenants = message.tenantList; 
+
+  $scope.ecdapp.deploymentInProgress = false;
+  $scope.ecdapp.validTenant = false;
+  let inputsAndDefaults = {};
+  let inputsAndDescriptions = {};
+
+  // Create an object for edit
+  $scope.ecdapp.editRequest = {
+      deployment_id : '',
+      type_id : message.blueprint.typeId,
+      fileModel : null,
+      parmFileDict : inputsAndDefaults,
+      descriptionDict : inputsAndDescriptions,
+      tenant : '',
+      component: message.blueprint.component,
+      tag : message.blueprint.typeName
+  };
+  // Fetch the blueprint
+  $scope.ecdapp.isDataLoading = true;
+  InventoryBlueprintService.viewBlueprint(message.blueprint.typeId).then(function(jsonObj) {
+    if (debug)
+      $log.debug("inventoryBlueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj));
+    if (jsonObj.error) {
+      $scope.ecdapp.errMsg = 'Request Failed';
+    }
+    else {
+      $scope.ecdapp.inputsDict = jsonObj.blueprintInputs;
+      for (var pkey in $scope.ecdapp.inputsDict) {
+        if (debug)
+          $log.debug('inventoryBlueprintDeployCtrl: checking key ' + pkey);
+        let dval = $scope.ecdapp.inputsDict[pkey].defaultValue;
+        let description = $scope.ecdapp.inputsDict[pkey].description;
+        if (  typeof dval === "undefined" )
+          dval = '';
+        if (  typeof description === "undefined" )
+          description = '';
+        inputsAndDefaults[pkey] = dval;
+        inputsAndDescriptions[pkey] = description;
+        if (debug)
+          $log.debug('inventoryBlueprintDeployCtrl: inputsAndDefaults: ' + JSON.stringify(inputsAndDefaults));
+     }
+    }
+    $scope.ecdapp.isDataLoading = false;
+  }, function(error) {
+    $scope.ecdapp.isDataLoading = false;
+    alert('Failed to get blueprint. Please retry.');
+    $log.error("blueprintViewCtrl failed: " + error);
+  });
+
+  $scope.ecdapp.validateTenant = function(){
+    if($scope.ecdapp.editRequest.tenant === "Select Tenant"){
+      $scope.ecdapp.validTenant = false;
+    }else{
+      $scope.ecdapp.validTenant = true;
+    }
+  }
+  /**
+   * Handler for file-read event reads file, parses JSON, validates content.
+   */
+  var fileReader = new FileReader();
+  fileReader.onload = function(event) {
+    let jsonString = fileReader.result;
+    if (debug)
+      $log.debug('fileReader.onload: read: ' + jsonString);
+    let ydict = {};
+    try {
+      ydict = JSON.parse(jsonString);
+    }
+    catch (ex) {
+      alert('Failed to parse file as JSON:\n' + ex);
     }
-       /**
-        * Handler for file-read event reads file, parses JSON, validates content.
-        */
-       var fileReader = new FileReader();
-       fileReader.onload = function(event) {
-               let jsonString = fileReader.result;
-               if (debug)
-                       $log.debug('fileReader.onload: read: ' + jsonString);
-               let ydict = {};
-               try {
-                       ydict = JSON.parse(jsonString);
-               }
-               catch (ex) {
-                       alert('Failed to parse file as JSON:\n' + ex);
-               }
-               // Process the file
-               for (var ykey in ydict) {
-                       let yval = ydict[ykey];
-                       if (debug)
-                               $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey);
-                       // Allow only expected keys with scalar values
-                       if (! (ykey in $scope.ecdapp.editRequest.parmFileDict))
-                               alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey);
-                       /*
+    // Process the file
+    for (var ykey in ydict) {
+      let yval = ydict[ykey];
+      if (debug)
+        $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey);
+      // Allow only expected keys with scalar values
+      if (! (ykey in $scope.ecdapp.editRequest.parmFileDict))
+        alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey);
+      /*
                        else if (typeof yval !== 'string' && typeof yval !== 'number')
                                alert('Unexpected file content:\nNot a simple key-value pair:\n' + ykey);
-                       */
-                       if (yval.constructor === {}.constructor)
-                               $scope.ecdapp.editRequest.parmFileDict[ykey] = angular.toJson(yval);
-                       else
-                               $scope.ecdapp.editRequest.parmFileDict[ykey] = yval;
-               }
-               if (debug)
-                       $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict));
-
-               // Update table in all cases 
-               $scope.$apply();
-       }
-
-       // Handler for file-select event
-       $scope.handleFileSelect = function() {
-               if (debug)
-                       $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name);
-               fileReader.readAsText($scope.ecdapp.editRequest.fileModel);
-       };
-               
-       /**
-        * Validates content of user-editable fields.
-        * Returns null if all is well, 
-        * a descriptive error message otherwise.
-        */
-       $scope.ecdapp.validateRequest = function(editRequest) {
-               if (editRequest == null)
-                       return 'No data found.\nPlease enter some values.';
-               if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '')
-                       return 'Deployment ID is required.\nPlease enter a value.';
-               if (editRequest.type_id == null || editRequest.type_id.trim() == '')
-                       return 'Type ID is required.\nPlease enter a value.';
-               if (editRequest.tag == null || editRequest.tag.trim() == '')
-                       return 'Deployment tag is required.\nPlease enter a value.';
-               if (editRequest.tenant == null || editRequest.tenant.trim() == '')
-                       return 'Tenant name is required.\nPlease enter a value.';
-               // Check that every file parameter is defined by blueprint
-               for (var pkey in $scope.ecdapp.editRequest.parmFileDict) {
-                       // Defined in blueprint?
-                       if (! $scope.ecdapp.inputsDict[pkey]) 
-                               return 'Unexpected input parameter\n' + pkey;
-               return null;
-               }
-       };
-
-       $scope.ecdapp.viewDeploymentExecutionsModalPopup = function(deployment) {
-               var modalInstance = $modal.open({
-                       templateUrl : 'inventory_execution_view_popup.html',
-                       controller : 'inventoryDeploymentExecutionsViewCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-jumbo',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               deployment : deployment
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       // No response.
-               });
-       };
-       $scope.ecdapp.deployBlueprint = function(editRequest) {
-               //editRequest.tenant = $rootScope.tenantList.tenant;
-               $scope.ecdapp.errMsg = '';
-               editRequest.deployment_id = editRequest.component + "_" + editRequest.tag;
-               if (debug)
-                       $log.debug('deployBlueprint: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest));
-               var validateMsg = $scope.ecdapp.validateRequest(editRequest);
-               if (validateMsg != null) {
-                       alert('Invalid Request:\n' + validateMsg);
-                       return;                 
-               }
-               // Create request with key:value parameters dictionary
-               let deploymentRequestObject =   {
-                       deploymentId : editRequest.deployment_id,
-                       serviceTypeId : editRequest.type_id,
-                       inputs : {},
-                       tenant : editRequest.tenant,
-                       method : "create"
-               };
-               let deploymentExecObj = {
-                               deploymentRef : editRequest.deployment_id,
-                               tenant : editRequest.tenant
-               }
-               for (var pkey in $scope.ecdapp.editRequest.parmFileDict)
-                       try {
-                               deploymentRequestObject.inputs[pkey] = angular.fromJson($scope.ecdapp.editRequest.parmFileDict[pkey]);
-                       } catch (error) {
-                               deploymentRequestObject.inputs[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey];
-                       }
-               if (debug) 
-                       $log.debug('deployBlueprint: deploymentRequestObject is ' + JSON.stringify(deployRequestObject));
-
-               $scope.ecdapp.deploymentInProgress = true;
-               InventoryDeploymentService.deployBlueprint(deploymentRequestObject)
-                       .then(function(response) {
-                               $scope.ecdapp.deploymentInProgress = false;
-                               if (response.error) {
-                                       $scope.ecdapp.errMsg = 'Failed to deploy blueprint: ' + response.error; 
-                                       alert('Failed to deploy blueprint:\n' + response.error);
-                               }
-                               else {
-                                       $modalInstance.close(response);
-                                       // launch the view executions modal
-                                       $scope.ecdapp.viewDeploymentExecutionsModalPopup(deploymentExecObj);
-                               }
-                       },
-                       function (error) {
-                               $log.error('inventoryBlueprintDeployCtrl: error while deploying: ' + error);
-                               $scope.ecdapp.errMsg = 'Server rejected deployment request: ' + error; 
-                               alert('Server rejected deployment request:\n' + error);
-                               $scope.ecdapp.deploymentInProgress = false;
-                       }
-               );
-       };
+       */
+      if (yval.constructor === {}.constructor)
+        $scope.ecdapp.editRequest.parmFileDict[ykey] = angular.toJson(yval);
+      else
+        $scope.ecdapp.editRequest.parmFileDict[ykey] = yval;
+    }
+    if (debug)
+      $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict));
+
+    // Update table in all cases 
+    $scope.$apply();
+  }
+
+  // Handler for file-select event
+  $scope.handleFileSelect = function() {
+    if (debug)
+      $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name);
+    fileReader.readAsText($scope.ecdapp.editRequest.fileModel);
+  };
+
+  /**
+   * Validates content of user-editable fields.
+   * Returns null if all is well, 
+   * a descriptive error message otherwise.
+   */
+  $scope.ecdapp.validateRequest = function(editRequest) {
+    if (editRequest == null)
+      return 'No data found.\nPlease enter some values.';
+    if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '')
+      return 'Deployment ID is required.\nPlease enter a value.';
+    if (editRequest.type_id == null || editRequest.type_id.trim() == '')
+      return 'Type ID is required.\nPlease enter a value.';
+    if (editRequest.tag == null || editRequest.tag.trim() == '')
+      return 'Deployment tag is required.\nPlease enter a value.';
+    if (editRequest.tenant == null || editRequest.tenant.trim() == '')
+      return 'Tenant name is required.\nPlease enter a value.';
+    // Check that every file parameter is defined by blueprint
+    for (var pkey in $scope.ecdapp.editRequest.parmFileDict) {
+      // Defined in blueprint?
+      if (! $scope.ecdapp.inputsDict[pkey]) 
+        return 'Unexpected input parameter\n' + pkey;
+      return null;
+    }
+  };
+
+  $scope.ecdapp.viewDeploymentExecutionsModalPopup = function(deployment) {
+    var modalInstance = $modal.open({
+      templateUrl : 'inventory_execution_view_popup.html',
+      controller : 'inventoryDeploymentExecutionsViewCtrl',
+      windowClass: 'modal-docked',
+      sizeClass: 'modal-jumbo',
+      resolve : {
+        message : function() {
+          var dataForPopup = {
+              deployment : deployment
+          };
+          return dataForPopup;
+        }
+      }
+    });
+    modalInstance.result.then(function(response) {
+      // No response.
+    });
+  };
+  $scope.ecdapp.deployBlueprint = function(editRequest) {
+    //editRequest.tenant = $rootScope.tenantList.tenant;
+    $scope.ecdapp.errMsg = '';
+    editRequest.deployment_id = editRequest.component + "_" + editRequest.tag;
+    if (debug)
+      $log.debug('deployBlueprint: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest));
+    var validateMsg = $scope.ecdapp.validateRequest(editRequest);
+    if (validateMsg != null) {
+      alert('Invalid Request:\n' + validateMsg);
+      return;                  
+    }
+    // Create request with key:value parameters dictionary
+    let deploymentRequestObject =      {
+        deploymentId : editRequest.deployment_id,
+        serviceTypeId : editRequest.type_id,
+        inputs : {},
+        tenant : editRequest.tenant,
+        method : "create"
+    };
+    let deploymentExecObj = {
+        deploymentRef : editRequest.deployment_id,
+        tenant : editRequest.tenant
+    }
+    for (var pkey in $scope.ecdapp.editRequest.parmFileDict)
+      try {
+        deploymentRequestObject.inputs[pkey] = angular.fromJson($scope.ecdapp.editRequest.parmFileDict[pkey]);
+      } catch (error) {
+        deploymentRequestObject.inputs[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey];
+      }
+      if (debug) 
+        $log.debug('deployBlueprint: deploymentRequestObject is ' + JSON.stringify(deployRequestObject));
+
+      $scope.ecdapp.deploymentInProgress = true;
+      
+      InventoryDeploymentService.deployBlueprint(deploymentRequestObject)
+      .then(function(response) {
+        $scope.ecdapp.deploymentInProgress = false;
+        if (response.error) {
+          $scope.ecdapp.errMsg = 'Failed to deploy blueprint: ' + response.error; 
+          alert('Failed to deploy blueprint:\n' + response.error);
+          InventoryDeploymentService.deleteBlueprint(editRequest.deployment_id, editRequest.tenant);
+        }
+        else {
+          $modalInstance.close(response);
+          // launch the view executions modal
+          $scope.ecdapp.viewDeploymentExecutionsModalPopup(deploymentExecObj);
+        }
+      },
+      function (error) {
+        $log.error('inventoryBlueprintDeployCtrl: error while deploying: ' + error);
+        $scope.ecdapp.errMsg = 'Server rejected deployment request: ' + error; 
+        alert('Server rejected deployment request:\n' + error);
+        $scope.ecdapp.deploymentInProgress = false;
+      }
+      );
+  };
 });
index b553c9e..02709d3 100644 (file)
@@ -35,11 +35,92 @@ appDS2.factory('InventoryBlueprintService', function ($http, $q, $log) {
                                return $q.reject(error.statusText);
                        });
                },
+               getBlueprintsSummary: function() {
+      // cache control for IE
+      let  cc = "&cc=" + new Date().getTime().toString();
+      let url = null;
+      url = 'inventory/dcae-service-types?_include=typeName,typeVersion,typeId' + cc;
+      return $http({
+          method: 'GET',
+          url: url,
+          cache: false,
+          responseType: 'json' 
+      }).then(function(response) {
+        if (response.data == null || typeof response.data != 'object') 
+          return $q.reject('InventoryBlueprintService.getBlueprintsSummary: response.data null or not object');
+        else 
+          return response.data;
+      }, 
+      function(error) {
+        $log.error('InventoryBlueprintService.getBlueprintsSummary failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });
+    },
+    getOwnersList: function() {
+      let url = 'inventory/owners';
+      return $http({
+        method: 'GET',
+        url: url,
+        cache: false,
+        responseType: 'json' 
+      }).then(function(response) {
+        if (response.data == null || typeof response.data != 'object') 
+          return $q.reject('InventoryBlueprintService.getOwnersList: response.data null or not object');
+        else 
+          return response.data;
+      }, 
+      function(error) {
+        $log.error('InventoryBlueprintService.getOwnersList failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });
+    },
+               getBlueprintsList: function() {
+      let url = 'inventory/service-type-list';
+      return $http({
+        method: 'GET',
+        url: url,
+        cache: false,
+        responseType: 'json' 
+      }).then(function(response) {
+        if (response.data == null || typeof response.data != 'object') 
+          return $q.reject('InventoryBlueprintService.getBlueprintsList: response.data null or not object');
+        else 
+          return response.data;
+      }, 
+      function(error) {
+        $log.error('InventoryBlueprintService.getBlueprintsList failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });
+    },
+    getBlueprintIdsList: function(searchBy) {
+      let url = '';
+      if (searchBy) {
+        url = 'inventory/service-type-id-list?searchBy=' + searchBy;
+      } else {
+        url = 'inventory/service-type-id-list';
+      }
+      return $http({
+        method: 'GET',
+        url: url,
+        cache: false,
+        responseType: 'json' 
+      }).then(function(response) {
+        if (response.data == null || typeof response.data != 'object') 
+          return $q.reject('InventoryBlueprintService.getBlueprintIdsList: response.data null or not object');
+        else 
+          return response.data;
+      }, 
+      function(error) {
+        $log.error('InventoryBlueprintService.getBlueprintIdsList failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });
+    },
                /**
                 *  get deployments for a blueprint
                 */
                getDeploymentForBp: function(bpArr) {
-                       let url = 'inventory/dcae-services/typeIds';    
+                 let url = 'deployment_blueprint_map';
+                       //let url = 'inventory/dcae-services/typeIds';  
                        return $http({
                                method: 'POST',
                                url: url,
@@ -49,7 +130,6 @@ appDS2.factory('InventoryBlueprintService', function ($http, $q, $log) {
                        if (response.data == null) 
                                return $q.reject('InventoryBlueprintService.getDeploymentForBp: response.data null or not object');
                        else {
-                console.log(response.data);
                 return response.data;
                        }
             },
@@ -166,7 +246,6 @@ appDS2.factory('InventoryBlueprintService', function ($http, $q, $log) {
                                if (response.data == null) 
                                        return $q.reject('InventoryBlueprintService.viewBlueprint: response.data null or not object');
                                else {
-                    console.log(response.data);
                     return response.data;
                 }
                        }, 
@@ -281,6 +360,12 @@ appDS2.factory('InventoryBlueprintService', function ($http, $q, $log) {
                },      
 */             
                deleteBlueprint: function(typeId) {
+                 /*var typeId = blueprint.typeId;
+                 var deploymentItems = blueprint.deployments.items;
+                 var deplIdList = [];
+                 for (var i=0; i < deploymentItems.length; i++) {
+                   deplIdList.push(deploymentItems.id);
+                 }*/
                        let url = 'inventory/dcae-service-types/' + typeId;
                        return $http({
                                        method: 'DELETE',
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/deployment-controllers.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/deployment-controllers.js
deleted file mode 100644 (file)
index e17dcae..0000000
+++ /dev/null
@@ -1,1352 +0,0 @@
-appDS2.controller('inventoryDeploymentTableController', function(
-               $rootScope, $scope, $routeParams, $route, 
-               $interval, $log, $modal, modalService, 
-               InventoryDeploymentService, InventoryBlueprintService) {
-
-       'use strict';
-
-       // Controls logging in this controller
-       var debug = false;
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       // models for controls on screen
-       $scope.ecdapp.tableData = [];
-       $scope.ecdapp.currentPageNum = 1;
-       $scope.ecdapp.viewPerPage = 10;
-       // other
-       $scope.ecdapp.errMsg = null;
-       $scope.ecdapp.isDataLoading = true;
-       $scope.ecdapp.isRequestFailed = false;
-       // sorting
-       $scope.ecdapp.sortBy = null;
-       // searching
-       $scope.ecdapp.searchBy = $routeParams.depId;
-       $scope.ecdapp.selectedRow = null;  // initialize our variable to null
-       $scope.ecdapp.setClickedRow = function(index){  //function that sets the value of selectedRow to current index
-               $scope.ecdapp.selectedRow = index;
-       }
-        
-       $scope.ecdapp.updateTable = function() {                        
-               $scope.ecdapp.isSrvcDataLoading = true;
-               var srvcIds = [];
-               var cloneGrid = $scope.ecdapp.tableData;        
-               angular.forEach($scope.ecdapp.tableData, function(item, index) {
-                         angular.forEach(item, function(value, key) {
-                                 if (key === "deploymentRef") {
-                                         srvcIds.push(value); 
-                                 }       
-                         });
-         });
-               
-               InventoryDeploymentService.getDeploymentStatus(srvcIds)
-               .then(function(jsonObj) {
-               if (jsonObj.error) {
-                       $log.error("inventoryDeploymentTableController.updateTable failed: " + jsonObj.error);
-               } else {
-                       for (var indx = 0; indx < jsonObj.length; indx++) {
-                               if (jsonObj[indx].status === "terminated") {
-                                       jsonObj[indx].status = "completed";
-                                       jsonObj[indx].statusImg = "static/fusion/images/active.png";
-                               } else {
-                                       jsonObj[indx].statusImg = "static/fusion/images/inactive.png";
-                               }
-                               cloneGrid[indx].statusInfo = jsonObj[indx];
-                       }
-                       $scope.ecdapp.tableData = cloneGrid;
-               }
-               $scope.ecdapp.isSrvcDataLoading = false;
-       }, function(error) {
-               $log.error("inventoryBlueprintController.updateTable failed: " + error);
-               $scope.ecdapp.isSrvcDataLoading = false;
-       });
-       }
-       /**
-        * Loads the table. Interprets the remote controller's response and copies
-        * to scope variables. The response is either a list to be assigned to
-        * tableData, or an error to be shown.
-        */
-       $scope.ecdapp.loadTable = function(sortBy, searchBy) {
-               $scope.ecdapp.isDataLoading = true;
-               $scope.ecdapp.sortBy = sortBy;
-               $scope.ecdapp.searchBy = searchBy;
-               InventoryDeploymentService.getDeployments($scope.ecdapp.currentPageNum,
-                               $scope.ecdapp.viewPerPage, sortBy, searchBy).then(
-                               function(jsonObj) {
-                                       if (jsonObj.error) {
-                                               $log.error("inventoryDeploymentController.loadTable failed: "
-                                                               + jsonObj.error);
-                                               $scope.ecdapp.isRequestFailed = true;
-                                               $scope.ecdapp.errMsg = jsonObj.error;
-                                               $scope.ecdapp.tableData = [];
-                                       } else {
-                                               $scope.ecdapp.isRequestFailed = false;
-                                               $scope.ecdapp.errMsg = null;
-                                               $scope.ecdapp.totalPages = jsonObj.totalPages;
-                                               $scope.ecdapp.tableData = jsonObj.items;
-                                               $scope.ecdapp.updateTable();
-                                       }
-                                       $scope.ecdapp.isDataLoading = false;
-                               },
-                               function(error) {
-                                       $log.error("inventoryDeploymentController.loadTable failed: "
-                                                       + error);
-                                       $scope.ecdapp.isRequestFailed = true;
-                                       $scope.ecdapp.errMsg = error;
-                                       $scope.ecdapp.tableData = [];
-                                       $scope.ecdapp.isDataLoading = false;
-                               });
-       };
-       
-       /**
-        * Loads the table. Interprets the remote controller's response and copies
-        * to scope variables. The response is either a list to be assigned to
-        * tableData, or an error to be shown.
-        */
-       $scope.ecdapp.sortTable = function(sortBy) {
-               $scope.ecdapp.isDataLoading = true;
-               $scope.ecdapp.sortBy = sortBy;
-               InventoryDeploymentService.getDeployments($scope.ecdapp.currentPageNum,
-                               $scope.ecdapp.viewPerPage, sortBy, $scope.ecdapp.searchBy).then(
-                               function(jsonObj) {
-                                       if (jsonObj.error) {
-                                               $log.error("inventoryDeploymentController.loadTable failed: "
-                                                               + jsonObj.error);
-                                               $scope.ecdapp.isRequestFailed = true;
-                                               $scope.ecdapp.errMsg = jsonObj.error;
-                                               $scope.ecdapp.tableData = [];
-                                       } else {
-                                               $scope.ecdapp.isRequestFailed = false;
-                                               $scope.ecdapp.errMsg = null;
-                                               $scope.ecdapp.totalPages = jsonObj.totalPages;
-                                               $scope.ecdapp.tableData = jsonObj.items;
-                                               $scope.ecdapp.updateTable();
-                                       }
-                                       $scope.ecdapp.isDataLoading = false;
-                               },
-                               function(error) {
-                                       $log.error("inventoryDeploymentController.loadTable failed: "
-                                                       + error);
-                                       $scope.ecdapp.isRequestFailed = true;
-                                       $scope.ecdapp.errMsg = error;
-                                       $scope.ecdapp.tableData = [];
-                                       $scope.ecdapp.isDataLoading = false;
-                               });
-       };
-       
-       /**
-        * Loads the table. Interprets the remote controller's response and copies
-        * to scope variables. The response is either a list to be assigned to
-        * tableData, or an error to be shown.
-        */
-       $scope.ecdapp.searchTable = function(searchBy) {
-               $scope.ecdapp.isDataLoading = true;
-               $scope.ecdapp.searchBy = searchBy;
-               InventoryDeploymentService.getDeployments($scope.ecdapp.currentPageNum,
-                               $scope.ecdapp.viewPerPage, $scope.ecdapp.sortBy, searchBy).then(
-                               function(jsonObj) {
-                                       if (jsonObj.error) {
-                                               $log.error("inventoryDeploymentController.loadTable failed: "
-                                                               + jsonObj.error);
-                                               $scope.ecdapp.isRequestFailed = true;
-                                               $scope.ecdapp.errMsg = jsonObj.error;
-                                               $scope.ecdapp.tableData = [];
-                                       } else {
-                                               $scope.ecdapp.isRequestFailed = false;
-                                               $scope.ecdapp.errMsg = null;
-                                               $scope.ecdapp.totalPages = jsonObj.totalPages;
-                                               $scope.ecdapp.tableData = jsonObj.items;
-                                               $scope.ecdapp.updateTable();
-                                       }
-                                       $scope.ecdapp.isDataLoading = false;
-                               },
-                               function(error) {
-                                       $log.error("inventoryDeploymentController.loadTable failed: "
-                                                       + error);
-                                       $scope.ecdapp.isRequestFailed = true;
-                                       $scope.ecdapp.errMsg = error;
-                                       $scope.ecdapp.tableData = [];
-                                       $scope.ecdapp.isDataLoading = false;
-                               });
-       };
-       
-       $scope.ecdapp.checkHelmStatus = function(deployment) {
-               var selTenant = deployment.statusInfo.tenant_name;
-               if ( typeof selTenant === "undefined" ) {
-                       selTenant = "default_tenant";
-               }
-               deployment.onlyLatest = true;
-               
-               // This object holds data for this operation
-               $scope.ecdapp.helmStatusRequest = {
-                               "deployment_id": deployment.deploymentRef,
-                               "workflow_name": "status",
-                               "tenant": selTenant
-               };
-               InventoryDeploymentService.helmStatusFlow($scope.ecdapp.helmStatusRequest).then(function(jsonObj) {
-                       if (debug)
-                               $log.debug("checkHelmStatus response: " + JSON.stringify(jsonObj));
-                       if (jsonObj.error) {
-                               $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error;
-                               $scope.ecdapp.updatingDeployment = false;
-                               $scope.ecdapp.isDataLoading = false;
-                       } else {
-                               console.log('%c POSTED helm status request', 'color: magenta; font-weight: bold;');
-                       }
-               }, function(error) {
-                                       $log.error('helmStatusFlow failed: ' + error);
-                               });
-               $scope.ecdapp.viewDeploymentExecutionsModalPopup(deployment);
-       };
-       /**
-        * Shows a modal pop-up with blueprint content.
-        * Passes data in via an object named "message". 
-        */
-       $scope.ecdapp.viewBlueprintDataModal = function(deployment) {
-               var modalInstance = $modal.open({
-                       templateUrl : 'blueprint_data_view_popup.html',
-                       controller : 'deployBlueprintViewCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-jumbo',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               blueprint : deployment
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-               });
-       };
-       
-       /**
-        * Invoked at first page load AND when
-        * user clicks on the B2B pagination control. 
-        */
-       $scope.pageChangeHandler = function(page) {
-               // console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page);
-               $scope.ecdapp.currentPageNum = page;
-               $scope.ecdapp.loadTable($scope.ecdapp.sortBy, $scope.ecdapp.searchBy);
-       }
-       
-       /**
-        * Shows a modal pop-up to confirm deletion. 
-        * On successful completion, updates the table.
-        */
-       $scope.ecdapp.deleteDeploymentModalPopup = function(deployment) {       
-               deployment.onlyLatest = true;
-               var modalInstance = $modal.open({
-                       templateUrl : 'inventory_deployment_delete_popup.html',
-                       controller : 'inventoryDeploymentDeleteCtrl',
-                       sizeClass: 'modal-small',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               deployment : deployment,
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       if (debug)
-                               $log.debug('deleteDeploymentPopup: response: ' + JSON.stringify(response));
-                       if (response == null) {
-                               // $log.debug('user closed dialog');
-                       }
-                       else {
-                               if (response.error != null) {
-                                       $log.error('deleteDeploymentModalPopup failed: ' + response.error);
-                                       alert('Failed to delete deployment:\n' + response.error);
-                               }
-                               else {
-                                       $scope.ecdapp.viewDeploymentExecutionsModalPopup(deployment);
-                               }
-                       }
-               });
-       };
-
-       /**
-        * Shows a modal pop-up with executions for a deployment.
-        * Passes data in via an object named "deployment".
-        */
-       $scope.ecdapp.viewDeploymentExecutionsModalPopup = function(deployment) {
-               var modalInstance = $modal.open({
-                       templateUrl : 'inventory_execution_view_popup.html',
-                       controller : 'inventoryDeploymentExecutionsViewCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-jumbo',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               deployment : deployment
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       // No response.
-               });
-       };
-       
-       /**
-        * Shows a modal pop-up with executions for a deployment.
-        * Passes data in via an object named "deployment".
-        */
-       $scope.ecdapp.viewDeploymentInputsModalPopup = function(deployment) {
-               var modalInstance = $modal.open({
-                       templateUrl : 'inventory_deployment_inputs_view_popup.html',
-                       controller : 'inventoryDeploymentInputsViewCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-jumbo',
-                       resolve : {
-                               message : function() {
-                                       var dataForPopup = {
-                                               deployment : deployment
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       // No response.
-               });
-       };
-
-       /**
-        * Shows a modal pop-up to initiate helm upgrade for a deployment
-        */
-       $scope.ecdapp.upgradeDeploymentModalPopup = function(deployment) {
-               //console.log(deployment);
-               var modalInstance = $modal.open({
-                       templateUrl: 'inventory_deployment_upgrade_popup.html',
-                       controller: 'inventoryDeploymentUpgradeCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-jumbo',
-                       resolve: {
-                               message: function() {
-                                       var dataForPopup = {
-                                               deployment : deployment
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       // No response.
-               });
-       };
-       
-       /**
-        * Shows a modal pop-up to initiate helm rollback for a deployment
-        */
-       $scope.ecdapp.rollbackDeploymentModalPopup = function(deployment) {
-               var modalInstance = $modal.open({
-                       templateUrl: 'inventory_deployment_rollback_popup.html',
-                       controller: 'inventoryDeploymentRollbackCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-jumbo',
-                       resolve: {
-                               message: function() {
-                                       var dataForPopup = {
-                                               deployment : deployment
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });
-               modalInstance.result.then(function(response) {
-                       // No response.
-               });
-       };
-       
-       /**
-        * Shows a modal pop-up to initiate update blueprint for a deployment
-        */
-       $scope.ecdapp.updateDeploymentModalPopup = function(deployment) {
-               var modalInstance = $modal.open({
-                       templateUrl: 'inventory_deployment_update_popup.html',
-                       controller: 'inventoryDeploymentUpdateCtrl',
-                       windowClass: 'modal-docked',
-                       sizeClass: 'modal-jumbo',
-                       resolve: {
-                               message: function() {
-                                       var dataForPopup = {
-                                               deployment : deployment
-                                       };
-                                       return dataForPopup;
-                               }
-                       }
-               });             
-       };
-       
-       /**
-        * Shows a modal pop-up to confirm service deletion. 
-        * On successful completion, updates the table.
-        */
-       $scope.ecdapp.deleteServiceModalPopup = function(service) {
-               modalService.popupConfirmWin("Confirm", "Delete Service with ID '"
-                               + service.serviceId + "'?", function() {
-                       InventoryDeploymentService.deleteService(service.serviceId).then(
-                                       function(response) {
-                                               if (debug)
-                                                       $log.debug('deleteServiceModalPopup: response: ' + JSON.stringify(response));
-                                               if (response && response.error) {
-                                                       alert('Failed to delete service:\n' + response.error);
-                                               }
-                                               else {
-                                                       // No response body on success.
-                                                       $scope.ecdapp.loadTable();
-                                               }
-                                       },
-                                       function(error) {
-                                               $log.error('InventoryDeploymentService.deleteService failed: ' + error);
-                                               alert('Service failed to delete service:\n' + error);
-                                       });
-               })
-       };
-});
-
-/*************************************************************************/
-
-appDS2.controller('inventoryDeploymentDeleteCtrl', function(
-               $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) {
-
-       'use strict';
-       
-       // Controls logging in this controller
-       var debug = false;
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'Undeploy?';
-       $scope.ecdapp.deploymentRef = message.deployment.deploymentRef;
-       var selTenant = message.deployment.statusInfo.tenant_name;
-       $scope.ecdapp.ui_tenant = selTenant;
-       $scope.ecdapp.tenant = selTenant;
-
-       $scope.ecdapp.deleteDeploymentById = function(){
-               InventoryDeploymentService.deleteDeployment($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(
-                       function(response) {
-                               if (debug)
-                                       $log.debug('inventoryDeploymentDeleteCtrl.deleteDeployment: ' + JSON.stringify(response));
-                               if (response && response.error) {
-                                       $log.error('InventoryDeploymentService.deleteDeployment failed: ' + response.error);
-                                       alert('Failed to delete deployment:\n' + response.error);
-                               }
-                               else {
-                                       // Delete service returns null on success.
-                                       $modalInstance.close("success");
-                               }
-                       },
-                       function(error) {
-                               $log.error('InventoryDeploymentService.deleteDeployment failed: ' + error);
-                               alert('Service failed to delete deployment:\n' + error);
-                       });
-       }
-
-});
-
-/*************************************************************************/
-
-appDS2.controller('inventoryDeploymentExecutionsViewCtrl', function(
-               $scope, $rootScope, $interval, $log, $modalInstance, message, modalService, InventoryExecutionService, ExecutionService) {
-
-       'use strict';
-
-       var debug = false;
-
-       if (debug)
-               $log.debug("inventoryDeploymentsExecutionsViewCtrl.message: " + JSON.stringify(message));
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       // models for controls on screen
-       $scope.ecdapp.label = 'Deployment Executions';
-       $scope.ecdapp.tableData = [];
-       $scope.ecdapp.logTableData = [];
-       $scope.ecdapp.currentPageNum = 1;
-       $scope.ecdapp.viewPerPage = 50;
-       $scope.ecdapp.currentLogPageNum = 1;
-       
-       // other
-       $scope.ecdapp.errMsg = null;
-       $scope.ecdapp.isDataLoading = true;
-       $scope.ecdapp.isEventLogQuery = false;
-       $scope.ecdapp.isRequestFailed = false;
-       $scope.ecdapp.isLastExecution = message.deployment.onlyLatest;
-       $scope.ecdapp.isLogType = true;
-    $scope.ecdapp.refresh_switch = {
-            value: true
-        };
-    $scope.ecdapp.options = {
-            "on":"On",
-            "off":"Off"
-        }   
-       var selTenant = 'default_tenant';
-       
-       if (typeof message.deployment.statusInfo === "undefined") {
-               selTenant = message.deployment.tenant;
-       } else {
-               selTenant = message.deployment.statusInfo.tenant_name;
-       }
-
-       $scope.ecdapp.ui_tenant = selTenant;
-       $scope.ecdapp.tenant = selTenant;
-       $scope.ecdapp.deplRef = message.deployment.deploymentRef;
-    var stop;
-       /**
-        * Loads the table. Interprets the remote controller's response and copies
-        * to scope variables. The response is either a list to be assigned to
-        * tableData, or an error to be shown.
-        */
-       $scope.ecdapp.loadTable = function() {
-               $scope.ecdapp.isDataLoading = true;
-               InventoryExecutionService.getExecutionsByDeployment(message.deployment.deploymentRef, 
-                               $scope.ecdapp.tenant,
-                               $scope.ecdapp.currentPageNum,
-                               $scope.ecdapp.viewPerPage).then(
-                               function(jsonObj) {
-                                       if (jsonObj.error) {
-                                               $log.error("inventoryDeploymentExecutionsViewCtrl.loadTable failed: "
-                                                               + jsonObj.error);
-                                               $scope.ecdapp.isRequestFailed = true;
-                                               if (jsonObj.error.includes("404")) {
-                                                       $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!";
-                                               }
-                                               $scope.ecdapp.tableData = [];
-                                       $scope.ecdapp.stopLoading();
-                                       } else {
-                                               $scope.ecdapp.isRequestFailed = false;
-                                               $scope.ecdapp.errMsg = null;
-                                               $scope.ecdapp.totalPages = jsonObj.totalPages;
-                                               var resultLen = jsonObj.items.length;
-                                               if (resultLen != undefined && resultLen > 0) {
-                                                       var exec_id = jsonObj.items[resultLen-1].id;
-                                                       if ($scope.ecdapp.isLastExecution) {
-                                                               $scope.ecdapp.tableData = [];
-                                                               $scope.ecdapp.tableData.push(jsonObj.items[resultLen-1]);
-                                                       } else {
-                                                               $scope.ecdapp.tableData = jsonObj.items;
-                                                       }
-                                                       $scope.ecdapp.getExecutionLogs(exec_id, $scope.ecdapp.tenant);
-                                               }
-                                       }
-                                       $scope.ecdapp.isDataLoading = false;
-                               },
-                               function(error) {
-                                       $log.error("inventoryDeploymentExecutionsViewCtrl.loadTable failed: "
-                                                       + error);
-                                       $scope.ecdapp.isRequestFailed = true;
-                                       $scope.ecdapp.errMsg = error;
-                                       $scope.ecdapp.tableData = [];
-                                       $scope.ecdapp.isDataLoading = false;
-                               $scope.ecdapp.stopLoading();
-                               });
-       };
-    $scope.$watch('ecdapp.refresh_switch["value"]', function(newValue,oldValue,scope) {
-       if (newValue != oldValue) {
-               if (newValue === true) {
-                       $scope.ecdapp.loadTable();
-                       stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 30000, 100, false);
-               } else {
-                       $scope.ecdapp.stopLoading();
-               }
-       }
-    }, true);
-
-    if ($scope.ecdapp.refresh_switch.value === true) {
-       stop = $interval( function(){ $scope.ecdapp.loadTable(); }, 30000, 100, false);
-    }
-    
-    $scope.ecdapp.stopLoading = function() {
-        if (angular.isDefined(stop)) {
-          $interval.cancel(stop);
-          stop = undefined;
-        }
-      };
-    
-       $scope.ecdapp.cancelExecutionModalPopup = function(execution, tenant) {
-               modalService.popupConfirmWin("Confirm", "Cancel execution with ID '"
-                               + execution.id + "'?", function() {
-                       $scope.ecdapp.isCancelOn = true;
-                       // TODO: gather action from user
-                       InventoryExecutionService.cancelExecution(execution.id, execution.deployment_id, "force-cancel", tenant).then(
-                                       function(response) {
-                                               if (debug)
-                                                       $log.debug("Controller.cancelExecutionModalPopup: " + JSON.stringify(response));
-                                               if (response && response.error) {
-                                                       // $log.error('cancelExectuion failed: ' + response.error);
-                                                       alert('Failed to cancel execution:\n' + response.error);
-                                                       $scope.ecdapp.isCancelOn = false;
-                                               }
-                                               else {
-                                                       // No response body on success.
-                                                       $scope.ecdapp.isCancelOn = false;
-                                                       $scope.ecdapp.loadTable();
-                                               }
-                                       },
-                                       function(error) {
-                                               $scope.ecdapp.isCancelOn = false;
-                                               $log.error('ExecutionService.cancelExecution failed: ' + error);
-                                               alert('Service failed to cancel execution:\n' + error);
-                                       });
-               })
-       };
-
-       /**
-        * Invoked at first page load AND when
-        * user clicks on the B2B pagination control.
-        */
-       $scope.pageChangeHandler = function(page) {
-               if (debug)
-                       console.log('pageChangeHandler: current is ' + $scope.ecdapp.currentPageNum + ' new is ' + page);
-               $scope.ecdapp.currentPageNum = page;
-               $scope.ecdapp.loadTable();
-
-       }
-       
-       $scope.ecdapp.selected = false;
-       $scope.ecdapp.toggleStatusDefinitions = function() {
-               $scope.ecdapp.selected = $scope.ecdapp.selected ? false :true;
-       }
-
-       /**
-        * Shows a modal pop-up with the error.
-        */
-       $scope.ecdapp.viewErrorModalPopup = function(row) {
-               $modalInstance.dismiss('cancel');
-               modalService.showFailure('Error Details', row.error, function() { } );
-       };
-       
-       $scope.ecdapp.getExecutionLogs = function(id, tenant) {
-               $scope.ecdapp.executionId = id;
-               $scope.ecdapp.isEventLogQuery = false;
-               InventoryExecutionService.getEventsByExecution(id , $scope.ecdapp.isLogType, tenant,
-                               $scope.ecdapp.currentLogPageNum, $scope.ecdapp.viewPerPage ).then(
-                               function(jsonObj) {
-                                       if (jsonObj.error) {
-                                               $log.error("inventoryDeploymentExecutionsViewCtrl.getExecutionLogs failed: "
-                                                               + jsonObj.error);
-                                               $scope.ecdapp.isEventLogQuery = false;
-                                               $scope.ecdapp.evtErrMsg = jsonObj.error;
-                                               $scope.ecdapp.logTableData = [];
-                                       } else {
-                                               $scope.ecdapp.isEventLogQuery = true;
-                                               $scope.ecdapp.evtErrMsg = null;
-                                               $scope.ecdapp.totalLogPages = jsonObj.totalPages;
-                                               $scope.ecdapp.logTableData = jsonObj.items;
-                                               /*
-                                               if ($scope.ecdapp.isLogType) {
-                                                       $scope.ecdapp.logTableData = jsonObj.items;
-                                               } else {
-                                                       $scope.ecdapp.logTableData = [];
-                                                       angular.forEach(jsonObj.items, function(item, index) {
-                                                                 angular.forEach(item, function(value, key) {
-                                                                         if (key === "type" && value != "cloudify_log") {
-                                                                                 $scope.ecdapp.logTableData.push(item); 
-                                                                         }       
-                                                                 });
-                                                       });
-                                               }
-                                               */
-                                       }
-                                       $scope.ecdapp.isDataLoading = false;
-                               },
-                               function(error) {
-                                       $log.error("inventoryDeploymentExecutionsViewCtrl.getExecutionLogs failed: "
-                                                       + error);
-                                       $scope.ecdapp.evtErrMsg = error;
-                                       $scope.ecdapp.logTableData = [];
-                                       $scope.ecdapp.isDataLoading = false;
-                               });
-       }
-
-    $scope.$on('$destroy', function() {
-        // Make sure that the interval is destroyed too
-        $scope.ecdapp.stopLoading();
-      });
-});
-
-/*************************************************************************/
-appDS2.controller('inventoryDeploymentInputsViewCtrl', function(
-               $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) {
-
-       'use strict';
-       
-       // Controls logging in this controller
-       var debug = false;
-       
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'Deployment Inputs';
-       $scope.ecdapp.deployment = null;
-       $scope.ecdapp.deploymentRef = message.deployment.deploymentRef;
-       $scope.ecdapp.serviceId = message.deployment.serviceId;
-       $scope.ecdapp.errMsg = null;
-       $scope.ecdapp.isDataLoading = true;
-       $scope.ecdapp.isRequestFailed = false;
-       var selTenant = message.deployment.statusInfo.tenant_name;
-       if ( typeof selTenant === "undefined" ) {
-               selTenant = "default_tenant";
-       }
-       $scope.ecdapp.ui_tenant = selTenant;
-       $scope.ecdapp.tenant = selTenant;
-
-       InventoryDeploymentService.getDeployment(message.deployment.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) {
-               if (deployment.items.length == 0) {
-                       $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!";
-                       $log.error("InventoryDeploymentSerice.getDeployment failed: "
-                                       + $scope.ecdapp.errMsg);
-                       $scope.ecdapp.isRequestFailed = true;
-               } 
-               // Deployment IDs are unique, so this will always return exactly one item!
-               // retrieve blueprintId and inputs of deployment.
-               else {
-                       $scope.ecdapp.errMsg = null;
-                       $scope.ecdapp.deployment = deployment.items[0];
-                       $scope.ecdapp.isRequestFailed = false;
-               }
-               $scope.ecdapp.isDataLoading = false;
-       },
-       function(error) {
-               $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error));
-               $scope.ecdapp.isRequestFailed = true;
-               $scope.ecdapp.errMsg = error;
-               $scope.ecdapp.isDataLoading = false;
-       });     
-});
-
-/*************************************************************************/
-appDS2.controller('inventoryDeploymentUpdateCtrl', function(
-               $scope, $log, $modalInstance, message, InventoryBlueprintService, InventoryDeploymentService) {
-
-       'use strict';
-       
-       var debug = false;
-       if (debug)
-               $log.debug("inventoryDeploymentUpdateCtrl.message: " + JSON.stringify(message));
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.deploymentInProgress = false;
-       $scope.ecdapp.serviceTypeComplete = false;
-       $scope.ecdapp.isDataLoading = true;
-       $scope.ecdapp.errMsg = null;
-       $scope.ecdapp.label = 'Update Deployment:  ' + message.deployment.deploymentRef;
-       $scope.ecdapp.deploymentRef = message.deployment.deploymentRef;
-       var selTenant = message.deployment.statusInfo.tenant_name;
-       if ( typeof selTenant === "undefined" ) {
-               selTenant = "default_tenant";
-       }
-       $scope.ecdapp.tenant = selTenant;
-       $scope.ecdapp.ui_tenant = selTenant;
-       $scope.ecdapp.typeName = '';
-       $scope.ecdapp.typeId = '';
-       $scope.ecdapp.inputsDict = {};
-       $scope.ecdapp.editRequest = {
-                       deployment_id : message.deployment.deploymentRef,
-                       type_id : '',
-                       fileModel : null,
-                       parmFileDict : {},
-                       tenant : $scope.ecdapp.tenant
-               };
-
-       // get the blueprints from inventory matching deployment reference filter
-       $scope.ecdapp.bp = [];
-       var sortBy = '';
-       var searchBy = message.deployment.deploymentRef.split("_", 1);
-       searchBy = searchBy[0];
-       InventoryBlueprintService.getBlueprints(1, 100, sortBy, searchBy)
-               .then(function(jsonObj) {
-               if (jsonObj.error) {
-                       $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + jsonObj.error);
-                       $scope.ecdapp.errMsg = jsonObj.error;
-                       $scope.ecdapp.bp = [];
-               } else {
-                       $scope.ecdapp.errMsg = null;
-                       $scope.ecdapp.bp = jsonObj.items;       
-                       if (Array.isArray($scope.ecdapp.bp) ) {
-                                 angular.forEach($scope.ecdapp.bp, function(item, index) {
-                                 item.checked = false;
-                         });
-                       }
-               }                       
-               $scope.ecdapp.isDataLoading = false;
-       }, function(error) {
-               $log.error("inventoryDeploymentUpdateCtrl.loadTable failed: " + error);
-               $scope.ecdapp.errMsg = error;
-               $scope.ecdapp.bp = [];
-               $scope.ecdapp.isDataLoading = false;
-       });
-       $scope.ecdapp.updateSelection = function(position) {
-               $scope.ecdapp.typeId = position;
-               $scope.ecdapp.editRequest.type_id = position;
-               angular.forEach($scope.ecdapp.bp, function(item, index) {
-                 if (position != index+1) 
-                         item.checked = false;
-               });
-       }
-       $scope.ecdapp.getBlueprint = function() {
-               $scope.ecdapp.isDataLoading = true;
-               InventoryBlueprintService.viewBlueprint($scope.ecdapp.typeId).then(function(jsonObj) {
-                       if (debug)
-                               $log.debug("inventoryDeploymentUpdateCtrl.viewBlueprint response: " + JSON.stringify(jsonObj));
-                       if (jsonObj.error) {
-                               $scope.ecdapp.errMsg = 'Request Failed';
-                               $scope.ecdapp.serviceTypeComplete = false;
-                               $scope.ecdapp.isDataLoading = false;
-                       }
-                       else {
-                               $scope.ecdapp.typeName = jsonObj.typeName;
-                               $scope.ecdapp.typeVersion = jsonObj.typeVersion;
-                               $scope.ecdapp.inputsDict = jsonObj.blueprintInputs;
-                               // query the current deployment inputs
-                               InventoryDeploymentService.getDeployment(message.deployment.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) {
-                                       if (deployment.items.length == 0) {
-                                               $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!";
-                                               $log.error("InventoryDeploymentSerice.getDeployment failed: "
-                                                               + $scope.ecdapp.errMsg);
-                                               //$scope.ecdapp.isRequestFailed = true;
-                                               $scope.ecdapp.serviceTypeComplete = true;
-                                       } 
-                                       // Deployment IDs are unique, so this will always return exactly one item!
-                                       // retrieve inputs of deployment.
-                                       else {
-                                               $scope.ecdapp.errMsg = null;
-                                               $scope.ecdapp.deployment = deployment.items[0];
-                                               // Copy the input parameter names and default values
-                                               let inputsAndDefaults = {};
-                                               for (var pkey in $scope.ecdapp.inputsDict) {
-                                                       if (debug)
-                                                               $log.debug('inventoryDeploymentUpdateCtrl: checking key ' + pkey);
-                                                       let dval = $scope.ecdapp.deployment.inputs[pkey];
-                                                               //$scope.ecdapp.inputsDict[pkey].defaultValue;
-                                                       if (dval === undefined || dval === null) {
-                                                               dval = '';
-                                                       }
-                                                       inputsAndDefaults[pkey] = dval;
-                                               }
-                                               $scope.ecdapp.editRequest.parmFileDict = inputsAndDefaults;
-                                               $scope.ecdapp.editRequest.type_id = $scope.ecdapp.typeId;
-                                               if (debug)
-                                                       $log.debug('inventoryBlueprintDeployCtrl: inputsAndDefaults: ' + JSON.stringify(inputsAndDefaults));
-
-                                               $scope.ecdapp.serviceTypeComplete = true;
-                                               //$scope.$apply();
-                                       }
-                                       $scope.ecdapp.isDataLoading = false;
-                               },
-                               function(error) {
-                                       $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error));
-                                       $scope.ecdapp.isRequestFailed = true;
-                                       $scope.ecdapp.errMsg = error;
-                                       $scope.ecdapp.isDataLoading = false;
-                               });     
-                       }
-                       $scope.ecdapp.isDataLoading = false;
-               }, function(error) {
-                       $scope.ecdapp.isDataLoading = false;
-                       $scope.ecdapp.serviceTypeComplete = false;
-                       alert('Failed to get blueprint. Please retry with valid blueprint ID.');
-                       $log.error("inventoryDeploymentUpdateCtrl failed: " + error);
-               });
-       };
-
-               /**
-                * Handler for file-read event reads file, parses JSON, validates content.
-                */
-               var fileReader = new FileReader();
-               fileReader.onload = function(event) {
-                       let jsonString = fileReader.result;
-                       if (debug)
-                               $log.debug('fileReader.onload: read: ' + jsonString);
-                       let ydict = {};
-                       try {
-                               ydict = JSON.parse(jsonString);
-                       }
-                       catch (ex) {
-                               alert('Failed to parse file as JSON:\n' + ex);
-                       }
-                       // Process the file
-                       for (var ykey in ydict) {
-                               let yval = ydict[ykey];
-                               if (debug)
-                                       $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey);
-                               // Allow only expected keys with scalar values
-                               if (! (ykey in $scope.ecdapp.editRequest.parmFileDict))
-                                       alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey);
-                               if (yval.constructor === {}.constructor)
-                                       $scope.ecdapp.editRequest.parmFileDict[ykey] = angular.toJson(yval);
-                               else
-                                       $scope.ecdapp.editRequest.parmFileDict[ykey] = yval;
-                       }
-                       if (debug)
-                               $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.editRequest.parmFileDict));
-
-                       // Update table in all cases 
-                       $scope.$apply();
-               }
-
-               // Handler for file-select event
-               $scope.handleFileSelect = function() {
-                       if (debug)
-                               $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name);
-                       fileReader.readAsText($scope.ecdapp.editRequest.fileModel);
-               };
-               
-               $scope.ecdapp.validateRequest = function(editRequest) {
-                       if (editRequest == null)
-                               return 'No data found.\nPlease enter some values.';
-                       if (editRequest.deployment_id == null || editRequest.deployment_id.trim() == '')
-                               return 'Deployment ID is required.\nPlease enter a value.';
-                       if (editRequest.type_id == null || editRequest.type_id.trim() == '')
-                               return 'Type ID is required.\nPlease enter a value.';
-                       // Check that every file parameter is defined by blueprint
-                       for (var pkey in $scope.ecdapp.editRequest.parmFileDict) {
-                               // Defined in blueprint?
-                               if (! $scope.ecdapp.inputsDict[pkey]) 
-                                       return 'Unexpected input parameter\n' + pkey;
-                       }
-                       return null;
-               }
-               
-               $scope.ecdapp.updateDeployment = function(editRequest) {
-                       if (debug)
-                               $log.debug('deployBlueprint: editRequest is ' + JSON.stringify($scope.ecdapp.editRequest));
-                       var validateMsg = $scope.ecdapp.validateRequest(editRequest);
-                       if (validateMsg != null) {
-                               alert('Invalid Request:\n' + validateMsg);
-                               $scope.ecdapp.errMsg = validateMsg;
-                               return;                 
-                       }
-                       // Create request with key:value parameters dictionary
-                       let deploymentRequestObject =   {
-                               deploymentId : editRequest.deployment_id,
-                               serviceTypeId : editRequest.type_id,
-                               inputs : {},
-                               tenant : editRequest.tenant,
-                               method : "update"
-                       };
-                       for (var pkey in $scope.ecdapp.editRequest.parmFileDict)
-                               try {
-                                       deploymentRequestObject.inputs[pkey] = angular.fromJson($scope.ecdapp.editRequest.parmFileDict[pkey]);
-                               } catch (error) {
-                                       deploymentRequestObject.inputs[pkey] = $scope.ecdapp.editRequest.parmFileDict[pkey];
-                               }
-                       if (debug) 
-                               $log.debug('deployBlueprint: deploymentRequestObject is ' + JSON.stringify(deployRequestObject));
-
-                       $scope.ecdapp.deploymentInProgress = true;
-                       InventoryDeploymentService.deployBlueprint(deploymentRequestObject)
-                               .then(function(response) {
-                                       $scope.ecdapp.deploymentInProgress = false;
-                                       if (response.error) {
-                                               alert('Failed to deploy blueprint:\n' + response.error);
-                                               $scope.ecdapp.errMsg = response.error;
-                                       } else {
-                                               alert('Deployment update request sent successfully, query the execution status for final outcome');
-                                               $modalInstance.close(response);
-                                       }
-                               },
-                               function (error) {
-                                       $log.error('inventoryBlueprintDeployCtrl: error while deploying: ' + error);
-                                       alert('Server rejected deployment request:\n' + error);
-                                       $scope.ecdapp.deploymentInProgress = false;
-                               }
-                       );
-               };
-
-});
-
-
-/*************************************************************************/
-
-appDS2.controller('deployBlueprintViewCtrl', function(
-               $scope, $log, message, InventoryBlueprintService) {
-
-       'use strict';
-       
-       var debug = false;
-       
-       if (debug)
-               $log.debug("deployBlueprintViewCtrl.message: " + JSON.stringify(message));
-
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'View Blueprint ' + message.blueprint.deploymentRef;
-
-       var typeLink = message.blueprint.typeLink.href;
-    var n = typeLink.lastIndexOf("/");
-    var typeId = typeLink.substring(n+1);
-       // Fetch the blueprint
-       $scope.ecdapp.isDataLoading = true;
-       InventoryBlueprintService.viewBlueprint(typeId).then(function(jsonObj) {
-               if (debug)
-                       $log.debug("deployBlueprintViewCtrl.viewBlueprint response: " + JSON.stringify(jsonObj));
-               if (jsonObj.error) {
-                       $scope.ecdapp.errMsg = 'Request Failed';
-               }
-               else {
-                       $scope.ecdapp.typeName = jsonObj.typeName;
-                       $scope.ecdapp.blueprint = jsonObj.blueprintTemplate;
-               }
-               $scope.ecdapp.isDataLoading = false;
-       }, function(error) {
-               $scope.ecdapp.isDataLoading = false;
-               alert('Failed to get blueprint. Please retry.');
-               $log.error("blueprintViewCtrl failed: " + error);
-       });
-});
-
-/*************************************************************************/
-appDS2.controller('inventoryDeploymentRollbackCtrl', function(
-               $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) {
-
-       'use strict';
-       
-       // Controls logging in this controller
-       var debug = false;
-       
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'Deployment Rollback';
-       $scope.ecdapp.revisions = [];
-       $scope.ecdapp.deploymentRef = message.deployment.deploymentRef;         
-       $scope.ecdapp.serviceId = message.deployment.serviceId;
-       $scope.ecdapp.errMsg = null;
-       $scope.ecdapp.isDataLoading = true;
-       $scope.ecdapp.isRequestFailed = false;
-       $scope.ecdapp.updatingDeployment = false;
-       var selTenant = message.deployment.statusInfo.tenant_name;
-       if ( typeof selTenant === "undefined" ) {
-               selTenant = "default_tenant";
-       }
-       $scope.ecdapp.tenant = selTenant;
-       $scope.ecdapp.ui_tenant = selTenant;
-       $scope.ecdapp.local_revisions = [];
-       // This object holds data for this operation
-       $scope.ecdapp.rollbackRequest = {
-                       "deployment_id": message.deployment.deploymentRef,
-                       "workflow_name": "rollback",
-                       "tenant": selTenant,
-                       "revision": 1
-       };
-       
-       InventoryDeploymentService.getNodeInstanceVersions($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(nodeRunTime) {
-               if (nodeRunTime == null) {
-                       $scope.ecdapp.errMsg = "Failed to retrieve Node instance runtime information";
-                       $log.error("InventoryDeploymentSerice.getNodeInstanceVersions failed: "
-                                       + $scope.ecdapp.errMsg);
-                       $scope.ecdapp.isRequestFailed = true;                   
-               } else {
-                       $scope.ecdapp.errMsg = null;
-                       $scope.ecdapp.revisions = nodeRunTime.items[0].runtime_properties['helm-history'];
-                         if (Array.isArray($scope.ecdapp.revisions) ) {
-                                 var dLen = $scope.ecdapp.revisions.length;
-
-                                 for (var i = 1; i < dLen; i++) {
-                                   var str = $scope.ecdapp.revisions[i].replace(/\s+/g, ' ');
-                                   var itemStrArr = str.split(" ");
-                                   var itemLen = itemStrArr.length;
-                                   var revObj = {};
-                                   revObj.revision = itemStrArr[0].trim();
-                                   revObj.updated = itemStrArr.slice(1,5).toString().replace(/,/g, ' ');       
-                                   revObj.status = itemStrArr[6].trim();
-                                   revObj.chart = itemStrArr[7].trim();
-                                   revObj.description = itemStrArr.slice(8,itemLen).toString().replace(/,/g, ' ');
-                                   revObj.name = itemStrArr[0].trim();
-                                   revObj.checked = false;
-                                   $scope.ecdapp.local_revisions.push(revObj);
-                                 }
-                         }
-                       console.log($scope.ecdapp.local_revisions);
-                       $scope.ecdapp.isRequestFailed = false;
-               }
-               $scope.ecdapp.isDataLoading = false;
-       },
-       function(error) {
-               $log.error('InventoryDeploymentService.getNodeInstanceVersions failed: ' + JSON.stringify(error));
-               $scope.ecdapp.isRequestFailed = true;
-               $scope.ecdapp.errMsg = error;
-               $scope.ecdapp.isDataLoading = false;
-       });
-       $scope.ecdapp.updateSelection = function(position) {
-               $scope.ecdapp.rollbackRequest.revision = position;
-               angular.forEach($scope.ecdapp.local_revisions, function(item, index) {
-                 if (position != index+1) 
-                         item.checked = false;
-               });
-       }
-       /**
-        * rollback deployment based on parameters user enters/adjusts in modal popup
-        * First retrieves the node-id using the blueprintId
-        * Using the node-id and deploymentId, retrieves the node-instance-id
-        * Calls the update resource API, passing object with deploymentId, and changed parameters
-        */
-        $scope.ecdapp.rollbackWorkflow = function(revision) {
-               $scope.ecdapp.updatingDeployment = true;
-               $scope.ecdapp.isDataLoading = true;
-               InventoryDeploymentService.rollbackFlow($scope.ecdapp.rollbackRequest).then(function(jsonObj) {
-                       if (debug)
-                               $log.debug("inventoryDeploymentRollbackCtrl.rollbackWorkflow response: " + JSON.stringify(jsonObj));
-                       if (jsonObj.error) {
-                               $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error;
-                               $scope.ecdapp.updatingDeployment = false;
-                               $scope.ecdapp.isDataLoading = false;
-                       } else {
-                               console.log('%c ROLLBACK RESOURCES COMPLETED', 'color: magenta; font-weight: bold;');
-                               alert('Rollback request for ' + $scope.ecdapp.deploymentRef + ' successfully went through to Cloudiy. Rollback is now pending');
-                               $scope.ecdapp.updatingDeployment = false;
-                               $scope.ecdapp.isDataLoading = false;
-                       }
-                       }, function(error) {
-                                       $scope.ecdapp.updatingDeployment = false;
-                                       $log.error('inventoryDeploymentRollbackCtrl failed: ' + error);
-                                       alert('Failed to rollback Deployment ' + $scope.ecdapp.deploymentRef + '. Please retry.');
-                                       $scope.ecdapp.isDataLoading = false;
-                               });
-               }
-});
-
-/*************************************************************************/
-appDS2.controller('inventoryDeploymentUpgradeCtrl', function(
-               $scope, $rootScope, $log, $modalInstance, message, InventoryDeploymentService) {
-
-       'use strict';
-       
-       // Controls logging in this controller
-       var debug = false;
-       
-       // this object holds all app data and functions
-       $scope.ecdapp = {};
-       $scope.ecdapp.label = 'Deployment Upgrade';
-       $scope.ecdapp.deployment = null;
-       $scope.ecdapp.deploymentRef = message.deployment.deploymentRef;         //THIS IS THE BLUEPRINT ID
-       $scope.ecdapp.serviceId = message.deployment.serviceId;
-       $scope.ecdapp.errMsg = null;
-       $scope.ecdapp.isDataLoading = true;
-       $scope.ecdapp.isRequestFailed = false;
-       $scope.ecdapp.updatingDeployment = false;
-       var selTenant = message.deployment.statusInfo.tenant_name;
-       if ( typeof selTenant === "undefined" ) {
-               selTenant = "default_tenant";
-       }
-       $scope.ecdapp.tenant = selTenant;
-       $scope.ecdapp.ui_tenant = selTenant;
-       $scope.ecdapp.parmFileDict = {};
-       
-       // This object holds data for editing the input parameters
-       $scope.ecdapp.editRequest = {
-               deployment_id: '',
-               type_id: '',
-               fileModel: null,
-               resourceConstants: {},
-               resourceDefinitionChanges: {}
-       };
-       //First get the blueprintId associated with the deployment, along with the inputs of the deployment
-       InventoryDeploymentService.getDeployment(message.deployment.deploymentRef, $scope.ecdapp.tenant).then(function(deployment) {
-               if (deployment.items.length == 0) {
-                       $scope.ecdapp.errMsg = "404 - Deployment " + message.deployment.deploymentRef + " Not Found!";
-                       $log.error("InventoryDeploymentSerice.getDeployment failed: "
-                                       + $scope.ecdapp.errMsg);
-                       $scope.ecdapp.isRequestFailed = true;
-               } 
-               // Deployment IDs are unique, so this will always return exactly one item!
-               else {
-                       $scope.ecdapp.errMsg = null;
-                       $scope.ecdapp.deployment = deployment.items[0];
-                       $scope.ecdapp.isRequestFailed = false;
-                       $scope.ecdapp.editRequest.type_id = deployment.items[0].blueprint_id;
-                       $scope.ecdapp.parmFileDict = deployment.items[0].inputs;
-                       Object.keys($scope.ecdapp.parmFileDict).map(function(key, index) {
-                               if (key == 'config-format' || key == 'config-url' || key == 'chart-version' || key == 'chart-repo-url') {
-                                       $scope.ecdapp.editRequest.resourceDefinitionChanges[key] = $scope.ecdapp.parmFileDict[key];
-                               } else {
-                                       $scope.ecdapp.editRequest.resourceConstants[key] = $scope.ecdapp.parmFileDict[key];
-                               }
-                       });
-               }
-               $scope.ecdapp.isDataLoading = false;
-       },
-       function(error) {
-               $log.error('InventoryDeploymentService.getDeployment failed: ' + JSON.stringify(error));
-               $scope.ecdapp.isRequestFailed = true;
-               $scope.ecdapp.errMsg = error;
-               $scope.ecdapp.isDataLoading = false;
-       });
-
-       /**
-        * Validates content of user-editable fields.
-        * Returns null if all is well, 
-        * a descriptive error message otherwise.
-        */
-       $scope.ecdapp.validateRequest = function(editRequest) {
-               if (editRequest == null)
-                       return 'No data found.\nPlease enter some values.';
-               if (editRequest["chart-version"] == null || editRequest["chart-version"].trim() == '')
-                       return 'Chart version is required.\nPlease enter a value.';
-               if (!editRequest["config-format"] || editRequest["config-format"].trim() == '') {
-                       return 'config format is required.\nPlease enter a value.';
-               }
-               if (!editRequest["config-url"] || editRequest["config-url"].trim() == '') {
-                       return 'Config URL is required.\nPlease enter a value.';
-               }
-               return null;
-       };
-       
-       /**
-        * Helm upgrade for deployment based on parameters user enters in modal popup
-        * First retrieves the node-id using the blueprintId
-        * Using the node-id and deploymentId, retrieves the node-instance-id
-        * Calls the start execution API, passing object with deploymentId, and changed parameters
-        */
-
-        $scope.ecdapp.upgradeWorkflow = function(resourceDefinitionChanges) {
-               $scope.ecdapp.updatingDeployment = true;
-               let nodeId = '';
-
-               // validate request
-               var validateMsg = $scope.ecdapp.validateRequest(resourceDefinitionChanges);
-               if (validateMsg != null) {
-                       alert('Invalid Request:\n' + validateMsg);
-                       $scope.ecdapp.updatingDeployment = false;
-                       return;                 
-               }
-               //get node id from blueprint
-               InventoryDeploymentService.getBlueprint($scope.ecdapp.deploymentRef, $scope.ecdapp.tenant).then(function(blueprint) {
-                       if (debug)
-                               $log.debug("inventoryDeploymentUpgradeCtrl.getBlueprint response: " + JSON.stringify(blueprint));
-                       if  (blueprint.error) {
-                               $scope.ecdapp.errMsg = 'Request Failed: ' + blueprint.error;
-                               $scope.ecdapp.updatingDeployment = false;
-                       }
-                       else {
-                               //console.log('returned blueprint:' + blueprint);
-                               let count = 0;
-                               //console.log("number of node objects in array: " + blueprint.items[0].plan.nodes.length);
-                               //console.log(JSON.stringify(blueprint));
-                               blueprint.items[0].plan.nodes.map(function(node) {
-                                       if (node.type == 'onap.nodes.component') {
-                                               //want to get FIRST node with type 'cloudify.kubernetes.resources.Deployment' so only set nodeID for first matching type
-                                               if (count < 1) {
-                                                       nodeId = node.id;
-                                               }
-                                               count = count + 1;
-                                       }
-                               });
-                               //if no node has type 'cloudify.kubernetes.resources.Deployment', return message saying no deployment exists and exit (ie nodeId still is '')
-                               if (nodeId == '') {
-                                       alert('Failed to retrieve Node Id. No matching deployment found (no deployment exists)');
-                                       $scope.ecdapp.updatingDeployment = false;
-                                       return;
-                               }
-                               //found node id. now need to retrieve node-instance-id
-                               console.log('%c RETRIEVED NODE ID: ' + nodeId, 'color: orange; font-weight: bold;');
-                               let nodeInstanceId = '';
-                               InventoryDeploymentService.getNodeInstanceId($scope.ecdapp.deploymentRef, nodeId, $scope.ecdapp.tenant).then(function(jsonObj) {
-                                       if (debug)
-                                               $log.debug("inventoryDeploymentUpgradeCtrl.getNodeInstanceId response: " + JSON.stringify(jsonObj));
-                                       if (jsonObj.error) {
-                                               $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error;
-                                               $scope.ecdapp.updatingDeployment = false;
-                                       }
-                                       else {
-                                               //if nodeInstanceId is still '' then it wasn't found, stop flow)
-                                               if (jsonObj.items[0].id == '') {
-                                                       alert('Failed to retrieve Node Instance Id for Node Id' + nodeId);
-                                                       $scope.ecdapp.updatingDeployment = false;
-                                                       return;
-                                               }
-                                               //found node-instance-id. now need to update resources
-                                               nodeInstanceId = jsonObj.items[0].id;
-                                               console.log('%c RETRIEVED NODE INSTANCE ID:' + nodeInstanceId, 'color: green; font-weight: bold;');
-                                               //console.log(resourceDefinitionChanges);
-                                               InventoryDeploymentService.upgradeFlow($scope.ecdapp.deploymentRef, nodeInstanceId, resourceDefinitionChanges, $scope.ecdapp.tenant).then(function(jsonObj) {
-                                                       if (debug)
-                                                               $log.debug("inventoryDeploymentUpgradeCtrl.updateResources response: " + JSON.stringify(jsonObj));
-                                                       if (jsonObj.error) {
-                                                               $scope.ecdapp.errMsg = 'Request Failed: ' + jsonObj.error;
-                                                               $scope.ecdapp.updatingDeployment = false;
-                                                       }
-                                                       else {
-                                                               console.log('%c UPDATE RESOURCES COMPLETED', 'color: magenta; font-weight: bold;');
-                                                               //console.log(jsonObj);
-                                                               $scope.ecdapp.updatingDeployment = false;
-                                                               alert('Helm Upgrade request for ' + $scope.ecdapp.deploymentRef + ' successfully went through to Cloudiy. Upgrade is now pending');                                                             $modalInstance.dismiss('cancel');
-                                                       }
-                                               }, function(error) {
-                                                       $scope.ecdapp.updatingDeployment = false;
-                                                       alert('Failed to perform upgrade for Deployment Id ' + $scope.ecdapp.deploymentRef + ' and Node Instance Id ' + nodeInstanceId + '. Please retry.');
-                                                       $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error);
-                                               });
-                                       }
-                               }, function(error) {
-                                       $scope.ecdapp.updatingDeployment = false;
-                                       alert('Failed to get Node Instance Id for deploymentId ' + $scope.ecdapp.deploymentRef + ' and Node Id ' + nodeId + '. Please retry.');
-                                       $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error);
-                               });
-
-                       }
-               }, function(error) {
-                       $scope.ecdapp.updatingDeployment = false;
-                       alert('Failed to get blueprint for blueprintId ' + $scope.ecdapp.deploymentRef + '. Please retry.');
-                       $log.error('inventoryDeploymentUpgradeCtrl failed: ' + error);
-               });
-        };
-
-       /**
-        * Handler for file-read event reads file, parses JSON, validates content.
-        */
-
-       var fileReader = new FileReader();
-       fileReader.onload = function(event) {
-               let jsonString = fileReader.result;
-               if (debug)
-                       $log.debug('fileReader.onload: read: ' + jsonString);
-               let ydict = {};
-               try {
-                       ydict = JSON.parse(jsonString);
-               }
-               catch (ex) {
-                       alert('Failed to parse file as JSON:\n' + ex);
-               }
-               // Process the file
-               for (var ykey in ydict) {
-                       let yval = ydict[ykey];
-                       if (debug)
-                               $log.debug('fileReader.onload: typeof ' + ykey + ' is ' + typeof ykey);
-                       // Allow only expected keys with scalar values
-                       if (! (ykey in $scope.ecdapp.parmFileDict))
-                               alert('Unexpected file content:\nKey not defined by blueprint:\n' + ykey);
-                       if (yval.constructor === {}.constructor)
-                               $scope.ecdapp.parmFileDict[ykey] = angular.toJson(yval);
-                       else
-                               $scope.ecdapp.parmFileDict[ykey] = yval;
-               }
-               if (debug)
-                       $log.debug('fileReader.onload: parmFileDict: ' + JSON.stringify($scope.ecdapp.parmFileDict));
-
-               // Update table in all cases 
-               //$scope.ecdapp.setResourceDefinitionChanges($scope.ecdapp.editRequest.resourceDefinitionChanges, $scope.ecdapp.editRequest.parmFileDict);
-               Object.keys($scope.ecdapp.parmFileDict).map(function(key, index) {
-                       if (key == 'config-format' || key == 'config-url' || key == 'chart-version') {
-                               $scope.ecdapp.editRequest.resourceDefinitionChanges[key] = $scope.ecdapp.parmFileDict[key];
-                       } else {
-                               $scope.ecdapp.editRequest.resourceConstants[key] = $scope.ecdapp.parmFileDict[key];
-                       }
-               });
-               //$scope.$apply();
-       };
-
-       // Handler for file-select event
-       $scope.handleFileSelect = function() {
-               if (debug)
-                       $log.debug('handleFileSelect: $scope.ecdapp.fileModel.name is ' + $scope.ecdapp.editRequest.fileModel.name);
-               fileReader.readAsText($scope.ecdapp.editRequest.fileModel);
-       };
-
-});
\ No newline at end of file
index 3fa2b2c..7b7a177 100644 (file)
@@ -4,7 +4,7 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) {
                 * Gets one page of objects.
                 * @param {Number} pageNum - page number; e.g., 1 
                 * @param {Number} viewPerPage - number of items per page; e.g., 25
-                * @return {JSON} Response object from remote side
+                * @return {JSON} Response object from remote side.
                 */
                getDeployments: function(pageNum,viewPerPage,sortBy,searchBy) {
                        // cache control for IE
@@ -17,7 +17,7 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) {
                        } else if (searchBy) {
                                url = 'inventory/dcae-services?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&searchBy=' + searchBy + cc;
                        } else {
-                               url = url = 'inventory/dcae-services?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc;
+                               url = 'inventory/dcae-services?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc;
                        }
                        return $http({
                                        method: 'GET',
@@ -35,6 +35,94 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) {
                                return $q.reject(error.statusText);
                        });
                },
+               getDeploymentsAafFilter: function(pageNum,viewPerPage,aafUsername) {
+                       // cache control for IE
+                       let cc = "&cc=" + new Date().getTime().toString();
+                       let url = null;
+
+                       url = 'filtered-deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&inputKey=aaf_username' + '&inputValue=' + aafUsername + cc;
+
+                       return $http({
+                                       method: 'GET',
+                                       url: url,
+                                       cache: false,
+                                       responseType: 'json' 
+                       }).then(function(response) {
+                               if (response.data == null || typeof response.data != 'object') 
+                                       return $q.reject('InventoryDeploymentService.getDeploymentsAafFilter: response.data null or not object');
+                               else 
+                                       return response.data;
+                       }, 
+                       function(error) {
+                               $log.error('InventoryDeploymentService.getDeploymentsAafFilter failed: ' + JSON.stringify(error));
+                               return $q.reject(error.statusText);
+                       });
+               },
+               getDeploymentsDcaeTargetTypeFilter: function(pageNum,viewPerPage,dcaeTargetType) {
+                       // cache control for IE
+                       let cc = "&cc=" + new Date().getTime().toString();
+                       let url = null;
+
+                       url = 'filtered-deployments?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&inputKey=dcae_target_type' + '&inputValue=' + dcaeTargetType + cc;
+
+                       return $http({
+                                       method: 'GET',
+                                       url: url,
+                                       cache: false,
+                                       responseType: 'json' 
+                       }).then(function(response) {
+                               if (response.data == null || typeof response.data != 'object') 
+                                       return $q.reject('InventoryDeploymentService.getDeploymentsDcaeTargetTypeFilter: response.data null or not object');
+                               else 
+                                       return response.data;
+                       }, 
+                       function(error) {
+                               $log.error('InventoryDeploymentService.getDeploymentsDcaeTargetTypeFilter failed: ' + JSON.stringify(error));
+                               return $q.reject(error.statusText);
+                       });
+               },
+    getDeploymentCount: function(searchBy) {
+      let url = 'service-list-count';
+      if (searchBy) {
+        url = url + '?searchBy=' + searchBy;
+      }
+      return $http({
+        method: 'GET',
+        url: url,
+        cache: false,
+        responseType: 'json' 
+      }).then(function(response) {
+        if (response.data == null || typeof response.data != 'object') 
+          return $q.reject('InventoryDeploymentService.getDeploymentList: response.data null or not object');
+        else 
+          return response.data;
+      }, 
+      function(error) {
+        $log.error('InventoryDeploymentService.getDeploymentList failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });
+    },
+               getDeploymentList: function(searchBy) {
+                 let url = 'service-list';
+                 if (searchBy) {
+                   url = url + '?searchBy=' + searchBy;
+                 }
+      return $http({
+        method: 'GET',
+        url: url,
+        cache: false,
+        responseType: 'json' 
+      }).then(function(response) {
+        if (response.data == null || typeof response.data != 'object') 
+          return $q.reject('InventoryDeploymentService.getDeploymentList: response.data null or not object');
+        else 
+          return response.data;
+      }, 
+      function(error) {
+        $log.error('InventoryDeploymentService.getDeploymentList failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });
+               },
                getDeploymentStatus: function(srvcIds) {
                        let url = 'deployment-status';  
                        return $http({
@@ -128,6 +216,26 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) {
                                return $q.reject(error.statusText);
                        });
                },
+               deleteBlueprint: function(blueprintId, tenant) {
+                 let url = 'blueprints/' + blueprintId + '?tenant=' + tenant;
+      return $http({
+        method: 'DELETE',
+        url: url,
+        responseType: 'json'
+      }).then(function(response) {
+        if (response.data == null)  
+          return $q.reject('InventoryDeploymentService.deleteBlueprint: response.data null or not object');
+        else {
+          console.log('%c DELETE BLUEPRINT FOR ID ' + blueprintId, 'color: blue; font-weight: bold;');
+          console.log(response.data);
+          return response.data;
+        }
+      },
+      function(error) {
+        $log.error('InventoryDeploymentService.deleteBlueprint failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });
+               },
                getBlueprint: function(blueprintId, tenant) {
                        let url = 'blueprints/' + blueprintId + '?tenant=' + tenant;
                        //console.log("url: " + url);
@@ -191,6 +299,46 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) {
                                return $q.reject(error.statusText);
                        });
                },      
+    getNodeInstances: function(deploymentId, tenant) {
+      console.log("entered getNodeInstances service function");
+      let url = 'node-instances/' + deploymentId + '?tenant=' + tenant;
+      return $http({
+        method: 'GET',
+        url: url,
+        cache: false,
+        responseType: 'json'
+      }).then(function(response) {
+        if (response.data == null) 
+          return $q.reject('InventoryDeploymentService.getNodeInstances: response.data null or not object');
+        else {
+          return response.data;
+        }
+      },
+      function(error) {
+        $log.error('InventoryDeploymentService.getNodeInstances failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });
+    },
+    getNodeInstanceData: function(deploymentId, tenant) {
+      console.log("entered getNodeInstanceData service function");
+      let url = 'node-instances-data?deployment=' + deploymentId + '&tenant=' + tenant;
+      return $http({
+        method: 'GET',
+        url: url,
+        cache: false,
+        responseType: 'json'
+      }).then(function(response) {
+        if (response.data == null) 
+          return $q.reject('InventoryDeploymentService.getNodeInstanceData: response.data null or not object');
+        else {
+          return response.data;
+        }
+      },
+      function(error) {
+        $log.error('InventoryDeploymentService.getNodeInstances failed: ' + JSON.stringify(error));
+        return $q.reject(error.statusText);
+      });
+    },
                updateResources: function(deploymentId, nodeInstanceId, resource_definition_changes) {
                        let body = {
                                "deployment_id": deploymentId,
@@ -291,6 +439,7 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) {
                        let configFormat = resource_definition_changes["config-format"];
                        let chartUrl = resource_definition_changes["chart-repo-url"];
                        let chartVersion = resource_definition_changes["chart-version"];
+                       let configSet = resource_definition_changes["config-set"];
                        let body = {
                                "deployment_id": deploymentId,
                                "workflow_id": "upgrade",
@@ -298,11 +447,12 @@ appDS2.factory('InventoryDeploymentService', function ($http, $q, $log) {
                                "force": true,
                                "tenant": tenant,
                                "parameters": {
+                                       "config_set": configSet,
                                        "node_instance_id": nodeInstanceId,
+                                       "chart_version": chartVersion,
+                                       "chart_repo_url": chartUrl,
                                        "config_url": configUrl,
-                                       "config_format": configFormat,
-                                       "chartRepo": chartUrl,
-                                       "chartVersion": chartVersion
+                                       "config_format": configFormat
                                }
                        };
                        let urlStr = 'executions';
index a4181f4..a756a2b 100644 (file)
@@ -6,6 +6,64 @@ appDS2.factory('InventoryExecutionService', function ($http, $q, $log) {
                 * @param {Number} viewPerPage - number of items per page; e.g., 25
                 * @return {JSON} Response object from remote side
                 */
+          getActiveExecutions: function(pageNum, viewPerPage) {
+       let cc = "&cc=" + new Date().getTime().toString();
+            let url = 'executions/active?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + cc;
+       return $http({
+         method: 'GET',
+         url: url,
+         cache: false,
+         responseType: 'json' 
+       }).then(function(response) {
+         if (response.data == null || typeof response.data != 'object') 
+           return $q.reject('InventoryExecutionService.getActiveExecutions: response.data null or not object');
+         else 
+           return response.data;
+       }, 
+       function(error) {
+         $log.error('InventoryExecutionService.getActiveExecutions failed: ' + JSON.stringify(error));
+         return $q.reject(error.statusText);
+       });
+          },
+          getExecutionsById: function(id, tenant, pageNum, viewPerPage) {
+       let cc = "&cc=" + new Date().getTime().toString();
+       let url = 'executions/'+ id + '?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&tenant=' + tenant + '&status=' + status + cc;
+       return $http({
+         method: 'GET',
+         url: url,
+         cache: false,
+         responseType: 'json' 
+       }).then(function(response) {
+         if (response.data == null || typeof response.data != 'object') 
+           return $q.reject('InventoryExecutionService.getExecutionsById: response.data null or not object');
+         else 
+           return response.data;
+       }, 
+       function(error) {
+         $log.error('InventoryExecutionService.getExecutionsById failed: ' + JSON.stringify(error));
+         return $q.reject(error.statusText);
+       });
+          },
+          getExecutionsByTenant: function(tenant, status, pageNum, viewPerPage) {
+             // cache control for IE
+             let cc = "&cc=" + new Date().getTime().toString();
+             let url = 'executions/tenant?pageNum=' + pageNum + '&viewPerPage=' + viewPerPage + '&tenant=' + tenant + '&status=' + status + cc;
+             return $http({
+                 method: 'GET',
+                 url: url,
+                 cache: false,
+                 responseType: 'json' 
+             }).then(function(response) {
+               if (response.data == null || typeof response.data != 'object') 
+                 return $q.reject('InventoryExecutionService.getExecutionsByTenant: response.data null or not object');
+               else 
+                 return response.data;
+             }, 
+             function(error) {
+               $log.error('InventoryExecutionService.getExecutionsByTenant failed: ' + JSON.stringify(error));
+               return $q.reject(error.statusText);
+             });
+           },
                getExecutionsByDeployment: function(deploymentId, tenant, pageNum, viewPerPage) {
                        // cache control for IE
                        let cc = "&cc=" + new Date().getTime().toString();
index eed1dfe..d17c065 100644 (file)
@@ -1,5 +1,5 @@
 <script type="text/ng-template"
-       id="inventory_blueprint_update_popup.html">
+  id="inventory_blueprint_update_popup.html">
 
        <style>
        .ecd-parameter-table
                                Blueprint <span style="font-weight: bolder;background: aqua;">{{ecdapp.serviceType.typeName}}</span> upload is in progress... 
                        </div>
                </div>
+               <!-- show progress indicator -->
+               <div ng-show="ecdapp.isDataLoading">
+                       <div class="span" style="margin-bottom:20px;">
+                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
+                       Please wait while the content loads.
+               </div>
+               </div>
                <form name="updateForm">
                <div class="row-nowrap" style="margin-top:-20px;">
                        <div class="span4 form-row">
@@ -89,9 +96,9 @@
                <div class="span6 form-row">
                                <label class="span12" for="typeName">*Blueprint Version</label>
                                <div class="field-group tooltip-onclick"  b2b-tooltip>
-                                       <input type="text" id="typeVer" name="typeVer" class="span12" data-ng-model="ecdapp.serviceType.typeVersion" disabled="disabled">
+                                       <input type="text" id="typeVer" name="typeVer" class="span12" data-ng-model="ecdapp.serviceType.typeVersion">
                                        <button class="reset-field" type="button" aria-label="Reset text field"></button>
-                                       <button id="tooltipButton3" class="btn icon-content-listguide tooltip-element icon-tooltip" data-toggle="button" aria-label="Email help"   aria-describedby="tooltipContent4" >
+                                       <button id="tooltipButton33" class="btn icon-content-listguide tooltip-element icon-tooltip" data-toggle="button" aria-label="Email help"   aria-describedby="tooltipContent4" >
                        </button>
                        <div class="helpertext" tabindex="-1" role="tooltip" id="tooltipContent4">  
                                <div class="popover-title">Blueprint or Type version - a required input</div>  
        </div>
 
        <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-               <div class="cta-button-group in">
+               <div ng-hide="ecdapp.updateInProgress" class="cta-button-group in">
                        <button class="btn btn-alt btn-small" type="submit" ng-disabled="updateForm.$invalid"
                                        ng-click="ecdapp.updateBlueprint(ecdapp.serviceType);">
                                Save
        </div>
        
 </script>
-
 <script type="text/ng-template"
-       id="inventory_blueprint_upload_popup.html">
+  id="inventory_blueprint_upload_popup.html">
 
        <style>
        .ecd-parameter-table
                        </div>
                </div>
                <form name="uploadForm">
-               <div class="row-nowrap" style="margin-top:-20px;" ng-show="ecdapp.isImport">
+               <div class="row-nowrap" style="margin-top:-20px;" ng-show="ecdapp.isImport && ecdapp.isInternal">
                        <div class="span3 form-row" ng-class="{'error':uploadForm.appl.$touched && !ecdapp.validAppl}">
                                <div class="tooltip" b2b-tooltip trigger="focus">
                        <a  href="javascript:void(0)" class="tooltip-element" data-placement="bottom" role="button" aria-label="Help"  aria-describedby="tooltiptext1" >
                </div>  
                </div>
                </div>
-               <div class="row-nowrap" style="margin-top:-20px;" ng-hide="ecdapp.isImport">
+               <div class="row-nowrap" style="margin-top:-20px;" ng-show="!ecdapp.isImport && ecdapp.isInternal">
                        <div class="span3 form-row" ng-class="{'error':uploadForm.appl.$touched && !ecdapp.validAppl}">
                                <div class="tooltip" b2b-tooltip trigger="focus">
                        <a  href="javascript:void(0)" class="tooltip-element" data-placement="bottom" role="button" aria-label="Help"  aria-describedby="tooltiptext1" >
                        </div>
                                </div>
                                <div class="field-group">
-                               <select id="appl" name="appl" b2b-dropdown placeholder-text="Select Application" class="span8" data-ng-model="ecdapp.serviceTypeRequest.application" ng-change="ecdapp.selectAppComp(ecdapp.serviceTypeRequest.application)" required>
+                               <select id="appl" name="appl" b2b-dropdown placeholder-text="Select Application" 
+                               class="span8" data-ng-model="ecdapp.serviceTypeRequest.application" ng-change="ecdapp.selectAppComp(ecdapp.serviceTypeRequest.application)" required>
                                        <option b2b-dropdown-list option-repeat="d in ecdapp.apps" value="{{d}}">{{d}}</option>
                                </select>
                                </div>
                        </div>
                                </div>
                                <div class="field-group">
-                               <select b2b-dropdown name="comp" class="span8" placeholder-text="Select Component" data-ng-model="ecdapp.serviceTypeRequest.component" ng-change="ecdapp.validateComp()" ng-disabled="!ecdapp.validAppl" required>
+                                                       
+                               <select b2b-dropdown name="comp" class="span8" placeholder-text="Select Component"
+                               data-ng-init="ecdapp.serviceTypeRequest.component" 
+                               data-ng-model="ecdapp.serviceTypeRequest.component" ng-change="ecdapp.validateComp()" 
+                               ng-disabled="!ecdapp.validAppl" required>
                                        <option b2b-dropdown-list option-repeat="d in ecdapp.comps" value="{{d.cname}}">{{d.dname}}</option>
                                </select>
                                </div>
                </div>  
                </div>
                </div>
-               <div class="row-nowrap" ng-hide="ecdapp.isImport">
-                       <div id="addAppDiv" class="span12 row-nowrap" ng-show="ecdapp.enableAppForm">
-                       <div class="span4 form-row">
-                               <label>*Component Name</label>
-                               <div class="field-group tooltip-onclick"  b2b-tooltip>
-                                       <input type="text" class="span12" data-ng-model="ecdapp.newCompName" placeholder="Example: scheduler">
-                                       <button class="reset-field" type="button" aria-label="Reset text field"></button>
-                                       <button id="tooltipButton1" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Comp Name"   aria-describedby="tooltipContent1" >
-                       </button>
-                       <div class="helpertext" tabindex="-1" role="tooltip" id="tooltipContent1">  
-                               <div class="popover-title">Component name - a required input</div>  
-                               <div class="popover-content">
-                               <p>Component name is a sub-string of the application namespace in AAF. A non-admin user should only add a new component if that user's role belongs to the component namespace.</p>
-                               <strong class="hidden-spoken">Double tap to close help message.</strong>
-                               </div>
-                       </div>
-                   </div>
-               </div>
-                       <div class="span4 form-row">
-                               <label>*Component Display Name</label>
-                               <div class="field-group tooltip-onclick"  b2b-tooltip>
-                                       <input type="text" class="span12" data-ng-model="ecdapp.newCompDisplayName" placeholder="Example: ECOMP SCHEDULER" style="text-transform:uppercase">
-                                       <button class="reset-field" type="button" aria-label="Reset text field"></button>
-                                       <button id="tooltipButton2" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Email help"   aria-describedby="tooltipContent2" >
-                       </button>
-                       <div class="helpertext" tabindex="-1" role="tooltip" id="tooltipContent2">  
-                               <div class="popover-title">Component Display Name - a required input</div>  
-                               <div class="popover-content">
-                               <p>Component display name in selection menu</p>
-                               <strong class="hidden-spoken">Double tap to close help message.</strong>
-                               </div>
-                       </div>
-                   </div>
-               </div>
-               <div class="span1 form-row">
-                       <label></label>
-                       <div class="field-group" ng-click="ecdapp.addApplication(ecdapp.serviceTypeRequest.application, ecdapp.newCompId, 
-                       ecdapp.newCompName, ecdapp.newCompDisplayName);">
-                               <a href="" title="Add Component" class="icon-arrows-quick-sync ecd-icon-action"></a>
-                               </div>
-                       </div> 
-                       </div>      
-               </div>
                <div class="row-nowrap">
                        <div class="span6 form-row" ng-class="{'error':uploadForm.typeName.$touched && uploadForm.typeName.$invalid}">
                                <label class="span12" for="typeName">*Blueprint Name</label>
                                <div class="field-group tooltip-onclick"  b2b-tooltip>
                                        <input type="text" id="typeName" name="typeName" class="span12" data-ng-model="ecdapp.serviceTypeRequest.typeName" placeholder="Example: mso_helm_chart" required>
                                        <button class="reset-field" type="button" aria-label="Reset text field"></button>
-                                       <button id="tooltipButton3" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Email help"   aria-describedby="tooltipContent3" >
+                                       <button id="tooltipButton35" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Email help"   aria-describedby="tooltipContent3" >
                        </button>
                        <div class="helpertext" tabindex="-1" role="tooltip" id="tooltipContent3">  
                                <div class="popover-title">Blueprint or Type name - a required input</div>  
                                <div class="field-group tooltip-onclick"  b2b-tooltip>
                                        <input type="text" id="typeVer" name="typeVer" class="span12" data-ng-model="ecdapp.serviceTypeRequest.typeVersion" placeholder="Example: 181017" required>
                                        <button class="reset-field" type="button" aria-label="Reset text field"></button>
-                                       <button id="tooltipButton3" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Email help"   aria-describedby="tooltipContent4" >
+                                       <button id="tooltipButton41" class="btn icon-tooltip tooltip-element" data-toggle="button" aria-label="Email help"   aria-describedby="tooltipContent4" >
                        </button>
                        <div class="helpertext" tabindex="-1" role="tooltip" id="tooltipContent4">  
                                <div class="popover-title">Blueprint or Type version - a required input</div>  
                                <div class="popover-content">
-                               <p>Blueprint or Service Type version may be an integer, example: 10, 181017 or a semantic version string, example: 1902.01.03. Semantic version string is converted to an integer by removing "...", before inserting into inventory. This field is used to identify the blueprint template version or a component package version.</p>
+                               <p>Blueprint or Service Type version should be an integer. This field is used to identify the blueprint template version or a component package version.</p>
                                <strong class="hidden-spoken">Double tap to close help message.</strong>
                                </div>
                        </div>
        </div>
 
        <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-               <div class="cta-button-group in">
-                       <button class="btn btn-alt btn-small" type="submit" ng-disabled="uploadForm.$invalid || !ecdapp.validAppl || !ecdapp.validComp"
+               <div ng-hide="ecdapp.uploadInProgress" class="cta-button-group in">
+                       <button class="btn btn-alt btn-small" type="submit" ng-show="ecdapp.isInternal" ng-disabled="uploadForm.$invalid || !ecdapp.validAppl || !ecdapp.validComp"
+                                       ng-click="ecdapp.uploadBlueprint(ecdapp.serviceTypeRequest);">
+                               Save
+                       </button>
+                       <button class="btn btn-alt btn-small" type="submit" ng-show="!ecdapp.isInternal" ng-disabled="uploadForm.$invalid"
                                        ng-click="ecdapp.uploadBlueprint(ecdapp.serviceTypeRequest);">
                                Save
                        </button>
                </div>
        </div>
 </script>
-
 <script type="text/ng-template" id="inventory_blueprint_view_popup.html">
 
        <div class="b2b-modal-header ng-scope">
        </div>
 
 </script>
-
 <script type="text/ng-template"
-       id="inventory_blueprint_deploy_popup.html">
+  id="inventory_blueprint_deploy_popup.html">
 
        <style>
        .ecd-parameter-table
                        </div>
                                </div>
                                <select id="cldTenants" name="tenant" b2b-dropdown placeholder-text="Select Tenant" class="span8" data-ng-model="ecdapp.editRequest.tenant" ng-change="ecdapp.validateTenant()">
-                                       <option b2b-dropdown-list option-repeat="d in tenantList.data" value="{{d.name}}">{{d.name}}</option>
+                                       <option b2b-dropdown-list option-repeat="d in ecdapp.availableTenants" value="{{d}}">{{d}}</option>
                                </select>
                <div ng-if="deployForm.tenant.$touched && !ecdapp.validTenant" id="tenantDropdown" role="alert" class="error-msg" aria-live="polite" aria-atomic="true" >
                   <i class="icon-badgealert" aria-hidden="true"></i>
                </div>
                </div>
 
-               <div ng-hide="ecdapp.deploymentInProgress" class="row-nowrap">
+               <div ng-hide="ecdapp.isDataLoading" class="row-nowrap">
                        <div class="span12">
                                <div class="form-row">
                                        <label for="parameters">*Parameters</label>
                                <div class="ecd-parameter-table">
                                        <table id="parameters">
                                                <tr id="ecd-table-header">
-                                                       <th width="60%">Name</th>
-                                                       <th width="40%">Value</th>
+                                                       <th width="30%">Name</th>
+                                                       <!--<th width="40%">Description</th>-->
+                                                       <th width="70%">Value</th>
                                                </tr>
                                <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict">
                                                        <tr id="tr-rowData">
-                                                               <td ng-bind="pkey"/>
-                                                               <td><input id="parameterValue" class="span12" type="text" data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" autofocus/></td>
+                                                               <td>
+                                                               <div style="font-weight: bold;">{{pkey}}</div>  
+                                                               <div style="margin-top: 8px; font-weight: lighter;">{{ecdapp.editRequest.descriptionDict[pkey]}}</div>
+                                                               </td>
+                                                               <td><input json id="parameterValue" class="span12" type="text" data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" autofocus/></td>
                                                        </tr>
                                                </tbody>
                                        </table>
index 763d956..044db14 100644 (file)
 <div id="page-content">
-
-       <h1 class="heading-page" id="blueprints">Blueprints</h1>
-       <!-- show progress indicator -->
-       <div ng-show="ecdapp.isDataLoading">
-               <div class="span" style="margin-bottom:20px;">
-               <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-               Please wait while the content loads.
-           </div>
-       </div>
-
-       <div ng-hide="ecdapp.isDataLoading">
-               <div id="button-search-row">
-    <span class="tooltip" b2b-tooltip>
-            <a href="#" class="btn btn-alt btn-small tooltip-element" tabindex="0" role="button" data-placement="bottom" 
-            aria-label="Help" ng-click="ecdapp.uploadBlueprintModalPopup()" aria-describedby="tooltiptextBtn">
-            Create
-            <span class="arrow"></span>
-               </a>
-                       <span class="tooltip-wrapper">
-            <span class="tooltip-size-control">
-                <span id="tooltiptextBtn" role="tooltip" aria-live="polite" aria-hidden="true" class="helpertext" tabindex="-1">  
-                    <span class="popover-title">Upload a blueprint</span>  
-                    <span class="popover-content">
-                        <span>Click to open up a FORM to upload and create a new blueprint in inventory.</span>
-                        <strong class="hidden-spoken hidden-desktop">Double tap to close help message.</strong>
-                    </span>
-                </span>
-            </span>
-               </span>
+  <h1 class="heading-page" id="blueprint-page">Blueprints</h1>
+  
+    <!-- show progress indicator -->
+  <div ng-show="ecdapp.isDataLoading">
+    <div class="span" style="margin-bottom: 20px;">
+      <i class="icon-spinner small" role="img"
+        aria-label="Please wait while the content loads"></i> Please
+      wait while the content loads.
+    </div>
+  </div>
+  <div ng-hide="ecdapp.isDataLoading" style="margin-bottom: 20px;">
+    <span class="tooltip" b2b-tooltip> <a href="#"
+      class="btn btn-alt btn-small tooltip-element" tabindex="0"
+      role="button" data-placement="bottom" aria-label="Help"
+      ng-click="ecdapp.uploadBlueprintModalPopup()"
+      aria-describedby="tooltiptextBtn"> Upload <span class="arrow"></span>
+    </a> <span class="tooltip-wrapper"> <span
+        class="tooltip-size-control"> <span id="tooltiptextBtn"
+          role="tooltip" aria-live="polite" aria-hidden="true"
+          class="helpertext" tabindex="-1"> <span
+            class="popover-title">Upload a blueprint</span> <span
+            class="popover-content"> <span>Click to open
+                up a FORM to upload and create a new blueprint in
+                inventory.</span> <strong class="hidden-spoken hidden-desktop">Double
+                tap to close help message.</strong>
+          </span>
+        </span>
+      </span>
     </span>
-                       <div style="float:right;"> 
-                               <div class="group">
-                                       <button tabindex="-1" class="btn btn-small" title="Reset Filters" type="button" ng-click="ecdapp.loadTable()"><i class="icon-arrows-replay-restart"></i></button>
-                                       <input tabindex="0" class="btn btn-small" type="text" placeholder="Search Blueprints" ng-model="ecdapp.searchBy"></input>
-                               <button tabindex="1" class="btn btn-small" title="Search" type="button" ng-click="ecdapp.searchTable(ecdapp.searchBy)"><i class="ion-search"></i></button>
-                               </div>
-                       </div>
-               </div>
-       
-               <div ng-show="ecdapp.isRequestFailed">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-       
-               <div ng-hide="ecdapp.isRequestFailed">
-       
-               <div 
-                       b2b-table 
-                       id="blueprints-table"
-                       class="b2b-table-div" 
-                       table-data="ecdapp.tableData"
-                       current-page="ecdapp.currentPageIgnored"
-                       next-sort="ecdapp.nextSortIgnored">
-       
-                       <table>
-                       
-                           <thead b2b-table-row type="header"> 
-                                               <tr id="th-header-row">
-                                                       <th id="expandTableHeading0" b2b-table-header sortable="false" key="application" ng-click="ecdapp.sortTable('application')">Application</th>
-                                                       <th b2b-table-header sortable="false" key="component" ng-click="ecdapp.sortTable('component')">Component</th>
-                                                       <th b2b-table-header sortable="false" key="type_name" ng-click="ecdapp.sortTable('typeName')">Name</th>
-                                                       <th b2b-table-header sortable="false" key="type_version" ng-click="ecdapp.sortTable('typeVersion')">Version</th>
-                                                       <th b2b-table-header sortable="false" key="created_at" ng-click="ecdapp.sortTable('created')">Created Date</th>
-                                                       <th b2b-table-header sortable="false" key="deployment_ref">Deployments
-                                                               <button style="margin-bottom:-5px; box-shadow:0 0 0 0 rgba(0, 0, 0, 0.15); min-width:0;" tabindex="1" class="btn btn-small" title="Refresh Deployments" type="button" ng-click="ecdapp.updateTable()">
-                                                               <i class="icon-arrows-replay-restart"></i>
-                                                               </button>                                                       
-                                                               <div ng-show="ecdapp.isSrvcDataLoading">
-                                                                       <div class="span" style="margin-bottom:5px;">
-                                                                       <i class="icon-spinner small" role="img" aria-label="Deployment Info is loading"></i>
-                                                                       Deployment Info is loading
-                                                                   </div>
-                                                               </div>
-                                                       </th>
-                                                       <th b2b-table-header sortable="false">Actions</th>
-                                                       <th b2b-table-header sortable="false" key="owner" ng-click="ecdapp.sortTable('owner')">Owner</th>
-                                                       <th b2b-table-header sortable="false" key="type_id" ng-click="ecdapp.sortTable('typeId')">ID</th>
-                                               </tr>
-                                       </thead>
-                                       
-                           <tbody b2b-table-row type="body" ng-repeat="rowData in ecdapp.tableData">
-                                               <tr id="tr-rowData{{index}}" tabindex="0">
-                                                       <td b2b-table-body id="expandTable_t1_{{$index}}" headers="expandTableHeading0" 
-                                                               ng-bind="rowData.application"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.component" />
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.typeName" />
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.typeVersion" />
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.created | date : 'MM-dd-yyyy HH:mm:ss Z'" />
-                                                       <td b2b-table-body ng-class="{'b2b-td-noLeftBorder' : rowData.expanded}" style="padding-right:0px;">
-                                                               <span>{{rowData.deployments.totalCount}}
-                                                               <i ng-if="rowData.deployments.totalCount != 0" class="pull-right" aria-label="{{rowData.expanded ? 'Collapse row ' + rowData.deployments : 'Expand row ' + rowData.deployments}}" 
-                                                               ng-class="{'icon-accordion-plus': !rowData.expanded, 'icon-accordion-minus' : rowData.expanded}" 
-                                                               ng-click="rowData.expanded=!rowData.expanded" b2b-accessibility-click="13,32" tabindex="0" role="button" aria-expanded="false" 
-                                                               title="click to view service information"></i>
-                                                               </span>
-                                                       </td>
-                                                       <td b2b-table-body >
-                                                               <div class="btn-group btn-actions" style="margin-bottom:0;box-shadow:none;">
-                                                                       <button type="button" class="btn dropdown-toggle" data-toggle="dropdown" title="More Actions"><i class="icon-apps-marketplace"></i></button>                                                                    
-                                                                               <ul class="dropdown-menu">
-                                                                               <li>
-                                                                                       <div ng-click="ecdapp.viewBlueprintModalPopup(rowData);">
-                                                                                               <i class="icon-documents-book ecd-icon-action"></i><a href="">View</a>
-                                                                                       </div>          
-                                                                               </li>
-                                                                               <li>
-                                                                                       <div ng-click="ecdapp.exportJson(rowData);">
-                                                                                               <i class="icon-documents-copy ecd-icon-action"></i><a href="">Export</a>
-                                                                                       </div>          
-                                                                               </li>
-                                                                               <li>
-                                                                                               <div ng-show="rowData.canDeploy  && rowData.deployments.totalCount === 0" ng-click="ecdapp.updateBlueprintModalPopup(rowData);">
-                                                                                                       <i class="icon-misc-pen ecd-icon-action"></i><a href="">Update</a>
-                                                                                               </div>          
-                                                                                       </li>
-                                                                                       <li>
-                                                                                               <div ng-show="rowData.canDeploy" ng-click="ecdapp.deployBlueprintModalPopup(rowData);">
-                                                                                                       <i class="icon-arrows-download ecd-icon-action"></i><a href="">Deploy</a>
-                                                                                               </div>          
-                                                                                       </li>
-                                                                                       <li>
-                                                                                               <div ng-show="rowData.canDeploy  && rowData.deployments.totalCount === 0" ng-click="ecdapp.deleteBlueprintModalPopup(rowData);">
-                                                                                                       <i class="icon-misc-trash ecd-icon-action"></i><a href="">Delete</a>
-                                                                                               </div>          
-                                                                                       </li>
-                                                                               </ul>
-                                                               </div><!-- .btn-group -->
-                                               </td>
-                                                       <td b2b-table-body 
-                                                               ng-bind="rowData.owner" />
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.typeId" />
-                                               </tr>
-                                               <tr ng-show="rowData.expanded">
-                               <td colspan="6" class="b2b-td-noTopBorder" headers="expandTable_t1_{{$index}}">
-                            <p class="offscreen-text">Expanded Row details for {{rowData.deployments}}</p>
-                            <ul>
-                               <li class="mar-top-30" ng-repeat="srvcData in rowData.deployments.items">
-                                       <div> <span class="font-medium">{{$index+1}}</span> </div>      
-                                       <div class="b2b-leading-dots">
-                                               <span class="font-medium">Deployment ID</span>
-                                               <!--  <span class="pull-right" ng-bind="srvcData.serviceId"><a href="ecd#/idep/{{srvcData.serviceId}}"></a></span>-->
-                                               <span class="pull-right"><a href="ecd#/idep/{{srvcData.serviceId}}">{{srvcData.serviceId}}</a></span>
-                                       </div>
-                                       <div class="b2b-leading-dots">
-                                               <span class="font-medium">Created timestamp</span>
-                                               <span class="pull-right" ng-bind="srvcData.created | date : 'MM-dd-yyyy HH:mm:ss Z'"" />                                        
-                                       </div>
-                                       <div class="b2b-leading-dots">
-                                               <span class="font-medium">Modified timestamp</span>
-                                               <span class="pull-right" ng-bind="srvcData.modified | date : 'MM-dd-yyyy HH:mm:ss Z'"" />                                       
-                                       </div>
-                               </li>
-                               <br>
-                            </ul>
-                               </td>
-                    </tr>
-                                       </tbody>
-                               </table>
-                       </div> 
-               
-               <div b2b-pagination="" total-pages="ecdapp.totalPages" 
-                                               current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler"
-                                               role="navigation">
-               </div>
-                                                       
-               <div style="height: 10px;">
-                       <!-- space between page number and black footer -->
-               </div>
-               
-       </div><!-- loading -->
-       
-</div><!-- page content -->
+    </span>
+  </div>
+  <div id="button-search-row" style="width: 60%; margin-left: 45px; float:right; margin-top: -30px;"  
+    ng-hide="ecdapp.isDataLoading">
+      <div>
+        <div class="group">
+          <div class="advanced-search">
+            <button tabindex="-1"
+              style="position: absolute; margin-left: -35px; border: none; background: none; top: 5px;"
+              "class="btn btn-small" title="show unfiltered view"
+              type="button" ng-click="ecdapp.reloadTable()">
+              <i class="icon-arrows-replay-restart"></i>
+            </button>
+            <button tabindex="1"
+              style="position: absolute; border: none; background: none; margin-left: 5px; top: 5px;"
+              "class="btn btn-medium" type="button"
+              ng-click="ecdapp.filterBySvc()">
+              <i class="ion-search"></i>
+            </button>
+            <input type="text" style="padding-left: 50px;" 
+              class="advanced-search-input"
+              placeholder="Search Blueprints"
+              ng-model="ecdapp.searchString" 
+              ng-keydown="[13, 32].includes($event.keyCode) && ecdapp.filterBySvc()"></input>
+            <button type="button" id="show-menu-filters"
+              class="btn dropdown-toggle"
+              ng-click="ecdapp.toggleMoreFilters()"
+              data-toggle="dropdown" title="More Filters">
+              <i class="icon-controls-down"></i>
+            </button>
+          </div>
+        </div>
+        <div class="menu-filters" ng-show="ecdapp.showingMoreFilters">
+          <div class="group">
+            <label class="col-sm-3 control-label">Blueprints: </label>
+            <ui-select multiple ng-model="ecdapp.selectedBp"
+              theme="bootstrap" close-on-select="false"
+              title="Blueprint Name"> <ui-select-match
+              class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices
+              class="ui-select-choices"
+              repeat="bp in ecdapp.availableBp | filter:$select.search"
+              position='down'> {{bp}} </ui-select-choices> </ui-select>
+          </div>
+          <div class="group" ng-show="ecdapp.isInternal">
+            <label class="col-sm-3 control-label">Applications:
+            </label>
+            <ui-select multiple ng-model="ecdapp.selectedApp"
+              theme="bootstrap" close-on-select="false"
+              title="Application"> <ui-select-match
+              class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices
+              class="ui-select-choices"
+              repeat="app in ecdapp.apps | filter:$select.search"
+              position='down'> {{app}} </ui-select-choices> </ui-select>
+          </div>
+          <div class="group" ng-show="ecdapp.isInternal">
+            <label class="col-sm-3 control-label">Components: </label>
+            <ui-select multiple ng-model="ecdapp.selectedComp"
+              theme="bootstrap" close-on-select="false"
+              title="Component name"> <ui-select-match
+              class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices
+              class="ui-select-choices"
+              repeat="comp in ecdapp.availableComp | filter:$select.search"
+              position='down'> {{comp}} </ui-select-choices> </ui-select>
+          </div>
+          <div class="group" ng-hide="ecdapp.filterByUser">
+            <label class="col-sm-3 control-label">Owners: </label>
+            <ui-select multiple ng-model="ecdapp.selectedOwner"
+              theme="bootstrap" close-on-select="false"
+              title="Blueprint owner"> <ui-select-match
+              class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices
+              class="ui-select-choices"
+              repeat="owner in ecdapp.bpOwners | filter:$select.search"
+              position='down'> {{owner}} </ui-select-choices> </ui-select>
+          </div>
+          <div class="group" style="float: right;">
+            <button tabindex="-1" class="btn btn-small"
+              title="Reset Filters" type="button"
+              ng-click="ecdapp.resetFilters()">
+              <i class="icon-arrows-replay-restart"></i>
+            </button>
+            <button tabindex="1" class="btn btn-small"
+              title="Filtered search" type="button"
+              ng-click="ecdapp.extendedfilterSrch()">
+              <i class="ion-search"></i>
+            </button>
+          </div>
+        </div>
+      </div>
+      <div style="margin-left: 20px; margin-top: 10px;" title="Search filters">
+        <label for="checkbox3" class="checkbox"> 
+        <input id="checkbox3" type="checkbox" ng-model="ecdapp.filterByUser" ng-change="ecdapp.toggleUserFilt()" 
+        class="ng-valid ng-dirty ng-valid-parse ng-touched">
+        <i class="skin"></i><span>My Blueprints</span>
+        </label> 
+      </div>
+  </div>
+
+  <div ng-show="ecdapp.isRequestFailed">
+    <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
+  </div>
+  <div ng-hide="ecdapp.isRequestFailed" >
+    <div b2b-table id="blueprints-table" class="b2b-table-div"
+      table-data="ecdapp.tableData"
+      current-page="ecdapp.currentPageIgnored"
+      next-sort="ecdapp.nextSortIgnored">
+      <table>
+        <thead b2b-table-row type="header">
+          <tr id="th-header-row">
+            <th b2b-table-header sortable="false" key="type_name"
+              ng-click="ecdapp.sortTable('typeName')">Name</th>
+            <th b2b-table-header sortable="false" key="type_version"
+              ng-click="ecdapp.sortTable('typeVersion')">Version</th>
+            <th b2b-table-header sortable="false" key="created_at"
+              ng-click="ecdapp.sortTable('created')">Created Date</th>
+            <th b2b-table-header sortable="false" key="deployment_ref">
+              <button style="margin-bottom: -10px;box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.15);min-width: 0;margin-left: -20px;" tabindex="1" class="btn btn-small ng-scope" title="Refresh Deployments" type="button" ng-click="ecdapp.updateTable()">
+                <i class="icon-arrows-replay-restart"></i>
+                <span class="ng-scope">Deployments</span>
+              </button>
+              <div ng-show="ecdapp.isSrvcDataLoading" class="ng-scope ng-hide">
+                <div class="span" style="margin-bottom: 5px;">
+                  <i class="icon-spinner small" role="img" aria-label="Deployment Info is loading"></i>
+                  Deployment Info is loading
+                </div>
+              </div>
+            </th>
+            <th b2b-table-header sortable="false">Actions</th>
+            <th b2b-table-header sortable="false" key="component"
+              ng-click="ecdapp.sortTable('component')">Component</th>
+            <th b2b-table-header sortable="false" key="owner"
+              ng-click="ecdapp.sortTable('owner')">Owner</th>
+            <th b2b-table-header sortable="false" key="type_id"
+              ng-click="ecdapp.sortTable('typeId')">ID</th>
+          </tr>
+        </thead>
+        <tbody b2b-table-row type="body"
+          ng-repeat="rowData in ecdapp.tableData">
+          <tr id="tr-rowData{{index}}" tabindex="0">            
+            <td b2b-table-body ng-bind="rowData.typeName" />
+            <td b2b-table-body ng-bind="rowData.typeVersion" />
+            <td b2b-table-body
+              ng-bind="rowData.created | date : 'MM-dd-yyyy HH:mm:ss Z'" />
+            <td b2b-table-body ng-if="rowData.deployments == undefined">
+              0
+             </td>
+            <td b2b-table-body ng-if="rowData.deployments"
+              ng-class="{'b2b-td-noLeftBorder' : rowData.expanded}"
+              style="padding-right: 0px;"><span>{{rowData.deployments.totalCount}}
+                <i ng-if="rowData.deployments && rowData.deployments.totalCount != 0"
+                class="pull-right"
+                aria-label="{{rowData.expanded ? 'Collapse row ' + rowData.deployments : 'Expand row ' + rowData.deployments}}"
+                ng-class="{'icon-accordion-plus': !rowData.expanded, 'icon-accordion-minus' : rowData.expanded}"
+                ng-click="rowData.expanded=!rowData.expanded"
+                b2b-accessibility-click="13,32" tabindex="0"
+                role="button" aria-expanded="false"
+                title="click to view service information"></i>
+            </span></td>
+            <td b2b-table-body>
+              <div class="btn-group btn-actions"
+                style="margin-bottom: 0; box-shadow: none;">
+                <button type="button" class="btn dropdown-toggle"
+                  data-toggle="dropdown" title="More Actions">
+                  <i class="icon-apps-marketplace"></i>
+                </button>
+                <ul class="dropdown-menu">
+                  <li>
+                    <div
+                      ng-click="ecdapp.viewBlueprintModalPopup(rowData);">
+                      <i class="icon-documents-book ecd-icon-action"></i><a
+                        href="">View</a>
+                    </div>
+                  </li>
+                  <li>
+                    <div ng-click="ecdapp.exportJson(rowData);">
+                      <i class="icon-documents-copy ecd-icon-action"></i><a
+                        href="">Export</a>
+                    </div>
+                  </li>
+                  <li>
+                    <div
+                      ng-show="rowData.canDeploy  && (rowData.deployments == undefined || rowData.deployments.totalCount === 0)"
+                      ng-click="ecdapp.updateBlueprintModalPopup(rowData);">
+                      <i class="icon-misc-pen ecd-icon-action"></i><a
+                        href="">Update</a>
+                    </div>
+                  </li>
+                  <li>
+                    <div ng-show="rowData.canDeploy"
+                      ng-click="ecdapp.deployBlueprintModalPopup(rowData);">
+                      <i class="icon-arrows-download ecd-icon-action"></i><a
+                        href="">Deploy</a>
+                    </div>
+                  </li>
+                  <li>
+                    <div
+                      ng-show="rowData.canDeploy && (rowData.deployments == undefined || rowData.deployments.totalCount === 0)"
+                      ng-click="ecdapp.deleteBlueprintModalPopup(rowData);">
+                      <i class="icon-misc-trash ecd-icon-action"></i><a
+                        href="">Delete</a>
+                    </div>
+                  </li>
+                </ul>
+              </div>
+              <!-- .btn-group -->
+            </td>
+            <td b2b-table-body ng-bind="rowData.component" />
+            <td b2b-table-body ng-bind="rowData.owner" />
+            <td b2b-table-body ng-bind="rowData.typeId" />
+          </tr>
+          <tr ng-show="rowData.expanded">
+            <td colspan="6" class="b2b-td-noTopBorder"
+              headers="expandTable_t1_{{$index}}">
+              <p class="offscreen-text">Expanded Row details for
+                {{rowData.deployments}}</p>
+              <ul>
+                <li class="mar-top-30"
+                  ng-repeat="srvcData in rowData.deployments.items">
+                  <div>
+                    <span class="font-medium">{{$index+1}}</span>
+                  </div>
+                  <div class="b2b-leading-dots" ng-show="srvcData.tenant_name.length > 0">
+                      <span class="font-medium">Deployment ID</span> 
+                      <span class="pull-right">
+                      <a href="ecd#/idep/tenant:{{srvcData.tenant_name}};serviceRef:{{srvcData.id}}">
+                      {{srvcData.id}}
+                      </a>
+                      </span>
+                  </div>
+                  <div class="b2b-leading-dots" ng-show="srvcData.tenant_name.length == 0">
+                    <span class="font-medium">Deployment ID</span> <span
+                      class="pull-right" ng-bind="srvcData.id" />
+                  </div>
+                  <div class="b2b-leading-dots" ng-show="srvcData.tenant_name.length > 0">
+                    <span class="font-medium">Cloudify Tenant</span> <span
+                      class="pull-right" ng-bind="srvcData.tenant_name" />
+                  </div>
+                  <div class="b2b-leading-dots">
+                    <span class="font-medium">Created timestamp</span> <span
+                      class="pull-right"
+                      ng-bind="srvcData.created_at | date : 'MM-dd-yyyy HH:mm:ss Z'" " />
+                  </div>
+                  <div class="b2b-leading-dots">
+                    <span class="font-medium">Modified timestamp</span>
+                    <span class="pull-right"
+                      ng-bind="srvcData.updated_at | date : 'MM-dd-yyyy HH:mm:ss Z'" " />
+                  </div>
+                </li>
+                <br>
+              </ul>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+    <div b2b-pagination="" total-pages="ecdapp.totalPages"
+      current-page="ecdapp.currentPage"
+      click-handler="pageChangeHandler" role="navigation"></div>
+    <div style="height: 10px;">
+      <!-- space between page number and black footer -->
+    </div>
+  </div>
+  <!-- loading -->
+</div>
+<div style="height: 10px;">
+  <!-- space between page number and black footer -->
+</div>
+<!-- page content -->
index e9bf3ea..41c3115 100644 (file)
 <script type="text/ng-template" id="inventory_deployment_execute_popup.html">
-
-       <style>
-       .ecd-parameter-table
-       {
-           border:   0px;
-       overflow: auto;
-       }
-       .ecd-parameter-table th 
-       {
-               font-size: 1.4rem;
-       }
-       </style>
-
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content">
-
-               <div class="row-nowrap">
-                       <div class="span12">
-                               <div class="form-row">
-                                       <label for="blueprintId">Deployment ID</label>
-                                       <div class="field-group">
-                                               <!--autofocus is HTML5 attribute; doesn't work in Firefox-->
-                                               <input id="blueprintId" class="span12" type="text" data-ng-model="ecdapp.editRequest.deployment_id" autofocus/>
-                                       </div>
-                               </div>
-                       </div> 
-                       <div class="span12">
-                               <div class="form-row">
-                                       <label for="allowCustom">&nbsp;</label>
-                                       <div class="field-group">
-                               <label for="allowCustomParameters" class="checkbox">
-                               <input id="allowCustomParameters" type="checkbox" ng-model="ecdapp.editRequest.allow_custom_parameter" />
-                                                       <i class="skin"></i><span>Allow Custom Parameters</span>
-                       </label>
-                                       </div>
-                               </div>
-                       </div> 
-               </div>                  
-                       
-               <div class="row-nowrap">
-                       <div class="span12">
-                               <div class="form-row">
-                                       <label for="workflowName">Workflow Name</label>
-                                       <div class="field-group">
-                                               <select b2b-dropdown id="workflowName" name="workflowName" ng-model="ecdapp.editRequest.workflow_name.value" ng-change="selectWorkflowName()">
-                                                       <option b2b-dropdown-list option-repeat="w in ecdapp.editRequest.workflow_list" value="{{w}}">
-                                                               {{w}}
-                                                       </option>
-                                               </select>
-                                       </div>
-                               </div>                  
-                       </div>
-                       <div class="span12">
-                               <div class="form-row">
-                                       <label for="force">&nbsp;</label>
-                                       <div class="field-group">
-                               <label for="force" class="checkbox">
-                               <input id="force" type="checkbox" ng-model="ecdapp.editRequest.force" />
-                                                       <i class="skin"></i><span>Force</span>
-                       </label>
-                                       </div>
-                               </div>
-                       </div> 
-               </div>
-
-               <div class="row-nowrap">
-                       <div class="span12">
-                               <div class="form-row">
-                                       <label for="parameters">*Parameters</label>
-                               <div b2b-file-drop file-model="ecdapp.editRequest.fileModel" on-drop="handleFileSelect()" align="center">
-                                               <span b2b-file-link file-model="ecdapp.editRequest.fileModel" on-file-select="handleFileSelect()" >
-                                               Drag &amp; drop a parameters YAML file here, or click to browse.
-                                               </span>
-                               </div>
-                       </div>
-                               <div class="ecd-parameter-table">
-                                       <table id="parameters">
-                                               <tr id="ecd-table-header">
-                                                       <th width="40%">Name</th>
-                                                       <th width="60%">Value</th>
-                                               </tr>
-                               <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict">
-                                                       <tr id="tr-rowData">
-                                                               <td ng-bind="pkey"/>
-                                                               <td><input id="parameterValue" class="span12" type="text" data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" autofocus/></td>
-                                                       </tr>
-                                               </tbody>
-                                       </table>
-                               </div>
-                       </div>
-               </div>
-
-       </div>
-
-       <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-               <div class="cta-button-group in">
-                       <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="ecdapp.executeDeployment(ecdapp.editRequest);">
-                               Save
-                       </button>
-                       <button class="btn btn-small" type="button"
-                               ng-click="$dismiss('cancel')">
-                               Cancel
-                       </button>
-               </div>
-       </div>
-
+<style>
+.ecd-parameter-table {
+       border: 0px;
+       overflow: auto;
+}
+
+.ecd-parameter-table th {
+       font-size: 1.4rem;
+}
+</style>
+<div class="b2b-modal-header ng-scope">
+  <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
+  <div class="corner-button in">
+    <button type="button" class="close" aria-label="Close"
+      ng-click="$dismiss('cancel')"></button>
+  </div>
+</div>
+<div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+  role="region" aria-label="Modal body content">
+  <div class="row-nowrap">
+    <div class="span12">
+      <div class="form-row">
+        <label for="blueprintId">Deployment ID</label>
+        <div class="field-group">
+          <!--autofocus is HTML5 attribute; doesn't work in Firefox-->
+          <input id="blueprintId" class="span12" type="text"
+            data-ng-model="ecdapp.editRequest.deployment_id" autofocus />
+        </div>
+      </div>
+    </div>
+    <div class="span12">
+      <div class="form-row">
+        <label for="allowCustom">&nbsp;</label>
+        <div class="field-group">
+          <label for="allowCustomParameters" class="checkbox"> <input
+            id="allowCustomParameters" type="checkbox"
+            ng-model="ecdapp.editRequest.allow_custom_parameter" /> <i
+            class="skin"></i><span>Allow Custom Parameters</span>
+          </label>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div class="row-nowrap">
+    <div class="span12">
+      <div class="form-row">
+        <label for="workflowName">Workflow Name</label>
+        <div class="field-group">
+          <select b2b-dropdown id="workflowName" name="workflowName"
+            ng-model="ecdapp.editRequest.workflow_name.value"
+            ng-change="selectWorkflowName()">
+            <option b2b-dropdown-list
+              option-repeat="w in ecdapp.editRequest.workflow_list"
+              value="{{w}}">{{w}}</option>
+          </select>
+        </div>
+      </div>
+    </div>
+    <div class="span12">
+      <div class="form-row">
+        <label for="force">&nbsp;</label>
+        <div class="field-group">
+          <label for="force" class="checkbox"> <input id="force"
+            type="checkbox" ng-model="ecdapp.editRequest.force" /> <i
+            class="skin"></i><span>Force</span>
+          </label>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div class="row-nowrap">
+    <div class="span12">
+      <div class="form-row">
+        <label for="parameters">*Parameters</label>
+        <div b2b-file-drop file-model="ecdapp.editRequest.fileModel"
+          on-drop="handleFileSelect()" align="center">
+          <span b2b-file-link file-model="ecdapp.editRequest.fileModel"
+            on-file-select="handleFileSelect()"> Drag &amp; drop
+            a parameters YAML file here, or click to browse. </span>
+        </div>
+      </div>
+      <div class="ecd-parameter-table">
+        <table id="parameters">
+          <tr id="ecd-table-header">
+            <th width="40%">Name</th>
+            <th width="60%">Value</th>
+          </tr>
+          <tbody
+            ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict">
+            <tr id="tr-rowData">
+              <td ng-bind="pkey" />
+              <td><input id="parameterValue" class="span12"
+                type="text"
+                data-ng-model="ecdapp.editRequest.parmFileDict[pkey]"
+                autofocus /></td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+  </div>
+</div>
+<div class="b2b-modal-footer ng-scope ng-isolate-scope">
+  <div class="cta-button-group in">
+    <button class="btn btn-alt btn-small" type="button"
+      ng-click="ecdapp.executeDeployment(ecdapp.editRequest);">
+      Save</button>
+    <button class="btn btn-small" type="button"
+      ng-click="$dismiss('cancel')">Cancel</button>
+  </div>
+</div>
 </script>
-
-<script type="text/ng-template" id="inventory_deployment_delete_popup.html">
-       
-
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-               <div ng-hide="ecdapp.errMsg">
-                       <div class="row-nowrap" style="margin-bottom:10px; margin-left:10px;"">
-                               <div class="span6">
-                                       <label for="tenant">Tenant</label>
-                                       <!--not editable-->
-                                       <input id="tenant" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.ui_tenant"/>
-                               </div>
-                       </div>
-               </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content">
-               <div class="span12">
-                       <div class="form-row">                                  
-                               <div class="field-group">
-                                       <label>
-                                               Undeploy the deployment with ID '{{ecdapp.deploymentRef}}'?
-                                       </label>
-                               </div>
-                       </div>
-               </div>
-       </div>
-
-       <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-               <div class="cta-button-group in">
-                       <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="ecdapp.deleteDeploymentById(deployment);">
-                               Undeploy
-                       </button>
-                       <button class="btn btn-small" type="button"
-                               ng-click="$dismiss('cancel')">
-                               Cancel
-                       </button>
-               </div>
-       </div>
-
+<script type="text/ng-template"
+  id="inventory_deployment_delete_popup.html">
+<div class="b2b-modal-header ng-scope">
+  <h3 id="myModalLabel" modal-title="">
+    {{ecdapp.label}}
+    </h2>
+    <div class="corner-button in">
+      <button type="button" class="close" aria-label="Close"
+        ng-click="$dismiss('cancel')"></button>
+    </div>
+</div>
+<div ng-hide="ecdapp.errMsg">
+  <div class="row-nowrap"
+    style="margin-bottom: 10px; margin-left: 10px;"">
+    <div class="span6">
+      <label for="tenant">Tenant</label>
+      <!--not editable-->
+      <input id="tenant" class="span12" type="text" disabled="disabled"
+        data-ng-model="ecdapp.ui_tenant" />
+    </div>
+  </div>
+</div>
+<div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+  role="region" aria-label="Modal body content">
+  <div class="span12">
+    <div class="form-row">
+      <div class="field-group">
+        <label> Undeploy the deployment with ID
+          '{{ecdapp.deploymentRef}}'? </label>
+      </div>
+    </div>
+  </div>
+</div>
+<div class="b2b-modal-footer ng-scope ng-isolate-scope">
+  <div class="cta-button-group in">
+    <button class="btn btn-alt btn-small" type="button"
+         ng-disabled="ecdapp.isDisabled" 
+      ng-click="ecdapp.deleteDeploymentById(deployment);">
+      Undeploy</button>
+    <button class="btn btn-small" type="button"
+      ng-click="$dismiss('cancel')">Cancel</button>
+  </div>
+</div>
 </script>
-
-<script type="text/ng-template" id="inventory_deployment_inputs_view_popup.html">
-
-       <style>
-       .ecd-parameter-table
-       {
-           border:   1px;
-       overflow: auto;
-       }
-       .ecd-parameter-table th 
-       {
-               font-size: 1.4rem;
-       }
-       </style>
-
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content">
-
-               <!-- show progress indicator -->
-               <div ng-show="ecdapp.isDataLoading">
-                       <div class="span" style="margin-bottom:20px;">
-                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                       Please wait while the content loads.
-               </div>
-               </div>
-
-               <div ng-show="ecdapp.errMsg">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-                       
-               <div ng-hide="ecdapp.errMsg">
-                       <div class="row-nowrap" style="margin-bottom:10px;">
-                               <div class="span6">
-                                       <label for="tenant">Tenant</label>
-                                       <!--not editable-->
-                                       <input id="tenant" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.ui_tenant"/>
-                               </div>
-                       </div>
-               </div>
-       
-               <div ng-hide="ecdapp.errMsg">
-                       <div class="row-nowrap">
-                               <div class="span12">
-                                       <label for="deploymentRef">Deployment Ref</label>
-                                       <!--not editable-->
-                                       <input id="deploymentRef" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.deploymentRef"/>
-                               </div>
-                               <div class="span12">
-                                       <label for="serviceId">Service ID</label>
-                                       <!--not editable-->
-                                       <input id="serviceId" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.serviceId"/>
-                               </div> 
-                       </div>                  
-                       
-                       <div class="row-nowrap">
-                               <div class="span12">
-                                       <table id="parameters">
-                                               <tr id="ecd-table-header">
-                                                       <th width="40%">Name</th>
-                                                       <th width="60%">Value</th>
-                                               </tr>
-                               <tbody ng-repeat="(pkey, pval) in ecdapp.deployment.inputs">
-                                                       <tr id="tr-rowData">
-                                                               <td ng-bind="pkey"/>
-                                                               <td ng-bind="pval"/>
-                                                       </tr>
-                                               </tbody>
-                                       </table>
-                               </div>
-                       </div>
-               </div>
-       </div>
+<script type="text/ng-template"
+  id="inventory_deployment_inputs_view_popup.html">
+<style>
+.ecd-parameter-table {
+       border: 1px;
+       overflow: auto;
+}
+
+.ecd-parameter-table th {
+       font-size: 1.4rem;
+}
+</style>
+<div class="b2b-modal-header ng-scope">
+  <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
+  <div class="corner-button in">
+    <button type="button" class="close" aria-label="Close"
+      ng-click="$dismiss('cancel')"></button>
+  </div>
+</div>
+<div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+  role="region" aria-label="Modal body content">
+  <!-- show progress indicator -->
+  <div ng-show="ecdapp.isDataLoading">
+    <div class="span" style="margin-bottom: 20px;">
+      <i class="icon-spinner small" role="img"
+        aria-label="Please wait while the content loads"></i> Please
+      wait while the content loads.
+    </div>
+  </div>
+  <div ng-show="ecdapp.errMsg">
+    <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
+  </div>
+  <div ng-hide="ecdapp.errMsg">
+    <div class="row-nowrap" style="margin-bottom: 10px;">
+      <div class="span6">
+        <label for="tenant">Tenant</label>
+        <!--not editable-->
+        <input id="tenant" class="span12" type="text"
+          disabled="disabled" data-ng-model="ecdapp.ui_tenant" />
+      </div>
+    </div>
+  </div>
+  <div ng-hide="ecdapp.errMsg">
+    <div class="row-nowrap">
+      <div class="span12">
+        <label for="deploymentRef">Deployment Ref</label>
+        <!--not editable-->
+        <input id="deploymentRef" class="span12" type="text"
+          disabled="disabled" data-ng-model="ecdapp.deploymentRef" />
+      </div>
+      <div class="span12">
+        <label for="serviceId">Service ID</label>
+        <!--not editable-->
+        <input id="serviceId" class="span12" type="text"
+          disabled="disabled" data-ng-model="ecdapp.serviceId" />
+      </div>
+    </div>
+    <div class="row-nowrap">
+      <div class="span12">
+        <table id="parameters">
+          <tr id="ecd-table-header">
+            <th width="30%">Name</th>
+            <th width="70%">Value</th>
+          </tr>
+          <tbody ng-repeat="(pkey, pval) in ecdapp.deployment.parmFileDict">
+            <tr id="tr-rowData">
+                         <td> 
+                               <div style="font-weight: bold;">{{pkey}}</div>
+                               <div style="margin-top: 10px; font-weight: lighter;">
+                               {{ecdapp.deployment.descriptionDict[pkey]}}</div>
+                         </td>
+              <td> <pre>{{pval}}</pre></td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+  </div>
+</div>
 </script>
-<script type="text/ng-template" id="inventory_deployment_update_popup.html">
-
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content">
-
-               <div ng-show="ecdapp.errMsg">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-
-               <div class="row-nowrap">
-                       <div class="span12">
-                               <label for="deploymentRef">Deployment Ref</label>
-                               <input id="deploymentRef" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.deploymentRef"/>
-                       </div>
-                       <div class="span12">
-                               <label for="tenantName">Tenant Name</label>
-                                       <!--not editable-->
-                               <input id="tenantName" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.ui_tenant"/>
-                       </div>
-               </div>
-
-               <div ng-hide="ecdapp.isDataLoading" style="margin-top:20px;">
-               <div 
-                       b2b-table 
-                       id="service-type-table"
-                       class="b2b-table-div" 
-                       table-data="ecdapp.bp" >
-                       <table>    
-                           <thead b2b-table-row type="header"> 
-                                               <tr id="th-header-row">
-                                                       <th b2b-table-header>Blueprint Name</th>
-                                                       <th b2b-table-header>Blueprint Version</th>
-                                                       <th b2b-table-header>Type ID</th>
-                                                       <th b2b-table-header>Description</th>
-                                                       <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th>
-                                               </tr>
-                                       </thead>                                        
-                           <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.bp">
-                                               <tr id="tr-rowData">
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.typeName"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.typeVersion"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.typeId"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.blueprintDescription"/>
-                                                       <td b2b-table-body>
-                                                       <div class="form-row">
-                                               <label for="bpCb{{index}}" class="checkbox">
-                                               <input id="bpCb{{index}}" type="checkbox" ng-model="rowData.checked" ng-click="ecdapp.updateSelection(rowData.typeId)" />
-                                                               <i class="skin"></i>
-                                               </label>
-                                                       </div>
-                                               </td>
-                                               </tr>
-                                       </tbody>
-                               </table>
-                       </div> 
-               </div>
-               <div ng-hide="ecdapp.isDataLoading" class="row-nowrap" style="margin-top:20px;">
-                       <div class="span12">
-                               <label for="typeID">Blueprint[Service Type] ID</label>
-                               <input id="typeID" class="span12" type="text" data-ng-model="ecdapp.typeId" title="ID of the blueprint to use for the update"/>
-                       </div>
-                       <div class="cta-button-group in">
-                               <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="ecdapp.getBlueprint()">
-                                       Get Blueprint data
-                               </button>
-                       </div>
-               </div>
-
-               <!-- show progress indicator -->
-               <div ng-show="ecdapp.isDataLoading">
-                       <div class="span" style="margin-bottom:20px;">
-               <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-               Please wait while the content loads.
-               </div>
-               </div>
-
-               <div ng-hide="ecdapp.isDataLoading" class="row-nowrap">
-                       <div class="span12">
-                               <div class="form-row">
-                                       <label for="parameters">*Parameters</label>
-                                       <div b2b-file-drop file-model="ecdapp.editRequest.fileModel" on-drop="handleFileSelect()" align="center">
-                                               <span b2b-file-link file-model="ecdapp.editRequest.fileModel" on-file-select="handleFileSelect()" >
-                                               Drag &amp; drop a parameters JSON file here, or click to browse.
-                                                       </span>
-                               </div>
-                       </div>
-                               <div class="ecd-parameter-table">
-                                       <table id="parameters">
-                                               <tr id="ecd-table-header">
-                                                       <th width="40%">Name</th>
-                                                       <th width="60%">Value</th>
-                                               </tr>
-                               <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict">
-                                                       <tr id="tr-rowData">
-                                                               <td ng-bind="pkey"/>
-                                                               <td><input id="parameterValue" class="span12" type="text" data-ng-model="ecdapp.editRequest.parmFileDict[pkey]" autofocus/></td>
-                                                       </tr>
-                                               </tbody>
-                                       </table>
-                               </div>
-                       </div>
-               </div>
-       </div>
-
-               <!-- show progress indicator -->
-               <div ng-show="ecdapp.deploymentInProgress">
-                       <div class="span" style="margin-bottom:20px;">
-               <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-               Please wait while the task completes.
-               </div>
-               </div>
-
-               <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-                       <div class="cta-button-group in" ng-hide="ecdapp.deploymentInProgress">
-                       <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="ecdapp.updateDeployment(ecdapp.editRequest)" ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg">
-                                       Update
-                       </button>
-                       <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="$dismiss('cancel');">
-                               Close
-                       </button>
-                       </div>
-               </div>
-
+<script type="text/ng-template"
+  id="inventory_deployment_update_popup.html">
+<div class="b2b-modal-header ng-scope">
+  <h3 id="myModalLabel" modal-title="">{{ecdapp.label}}</h3>
+  <div class="corner-button in">
+    <button type="button" class="close" aria-label="Close"
+      ng-click="$dismiss('cancel')"></button>
+  </div>
+</div>
+<div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+  role="region" aria-label="Modal body content">
+  <div ng-show="ecdapp.errMsg">
+    <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
+  </div>
+  <div ng-hide="ecdapp.isDataLoading" style="margin-top: -5px;">
+    <div class="field-group">
+      <label for="bp">Blueprint</label> <select
+        style="font-size: 1.2rem;" id="bp" name="appl" b2b-dropdown
+        class="span6" ng-model="ecdapp.typeId"
+        ng-change="ecdapp.getBlueprint()" required>
+        <option b2b-dropdown-list option-repeat="d in ecdapp.bp"
+          value="{{d.typeId}}">{{d.typeName}}
+          version#{{d.typeVersion}}</option>
+      </select>
+    </div>
+  </div>
+  <!-- show progress indicator -->
+  <div ng-show="ecdapp.isDataLoading">
+    <div class="span" style="margin-bottom: 20px;">
+      <i class="icon-spinner small" role="img"
+        aria-label="Please wait while the content loads"></i> Please
+      wait while the content loads.
+    </div>
+  </div>
+  <div ng-hide="ecdapp.isDataLoading" class="row-nowrap">
+    <div class="span12">
+      <div class="form-row">
+        <label for="parameters">*Inputs</label>
+        <div b2b-file-drop file-model="ecdapp.editRequest.fileModel"
+          on-drop="handleFileSelect()" align="center">
+          <span b2b-file-link file-model="ecdapp.editRequest.fileModel"
+            on-file-select="handleFileSelect()"> Drag &amp; drop
+            a parameters JSON file here, or click to browse. </span>
+        </div>
+      </div>
+      <div class="ecd-parameter-table">
+        <table id="parameters">
+          <tbody
+            ng-repeat="(pkey, pval) in ecdapp.editRequest.parmFileDict">
+            <tr id="tr-rowData">
+              <td
+                style="padding: 5px 0 2px 0; font-size: 1.2rem; width: 100%; border: none;"
+                ng-bind="pkey">
+                               <div style="font-weight: bold;">{{pkey}}</div>  
+                               <div style="margin-top: 8px; font-weight: lighter;">{{ecdapp.editRequest.descriptionDict[pkey]}}</div>
+              </td>
+                       </tr>
+            <tr id="tr-rowData">
+              <td
+                style="padding: 0 5px 5px; font-size: 1.2rem; width: 100%; border: none;">
+                <input id="parameterValue" class="span12" type="text"
+                data-ng-model="ecdapp.editRequest.parmFileDict[pkey]"
+                autofocus />
+              </td>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+  </div>
+  <div style="border-bottom: 1px solid black;">Actions</div>
+  <div style="margin-top: 10px;">
+    <label for="install_flow" class="btn-switch-label"
+      ng-class="{'b2b-disabled-label':allDisabled}"> <input
+      type="button" aria-pressed="{{ecdapp.install_flow.value}}"
+      id="refresh_switch" b2b-switches
+      ng-model="ecdapp.install_flow.value" ng-disabled="allDisabled"
+      aria-disabled="{{allDisabled}}"
+      aria-label="Auto-refresh is {{ecdapp.install_flow.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}">
+      <label style="margin-left: 10px;" aria-hidden="true">Run
+        install workflow</label> <span class="tooltip" b2b-tooltip> <a
+        href="#" class="icon-tooltip tooltip-element" tabindex="0"
+        role="button" data-placement="top" aria-label="Help"
+        aria-describedby="tooltiptextRadio"> <span class="arrow"></span>
+      </a> <span class="tooltip-wrapper"> <span
+          class="tooltip-size-control"> <span
+            id="tooltiptextRadio" role="tooltip" aria-live="polite"
+            aria-hidden="true" class="helpertext" tabindex="-1">
+              <span class="popover-title">Run install lifecycle
+                operations</span> <span class="popover-content"> </span>
+          </span>
+        </span>
+      </span>
+    </span>
+    </label>
+  </div>
+  <div style="margin-top: 10px;">
+    <label for="uninstall_flow" class="btn-switch-label"
+      ng-class="{'b2b-disabled-label':allDisabled}"> <input
+      type="button" aria-pressed="{{ecdapp.uninstall_flow.value}}"
+      id="refresh_switch" b2b-switches
+      ng-model="ecdapp.uninstall_flow.value" ng-disabled="allDisabled"
+      aria-disabled="{{allDisabled}}"
+      aria-label="Auto-refresh is {{ecdapp.uninstall_flow.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}">
+      <label style="margin-left: 10px;" aria-hidden="true">Run
+        uninstall workflow</label> <span class="tooltip" b2b-tooltip> <a
+        href="#" class="icon-tooltip tooltip-element" tabindex="0"
+        role="button" data-placement="top" aria-label="Help"
+        aria-describedby="tooltiptextRadio"> <span class="arrow"></span>
+      </a> <span class="tooltip-wrapper"> <span
+          class="tooltip-size-control"> <span
+            id="tooltiptextRadio" role="tooltip" aria-live="polite"
+            aria-hidden="true" class="helpertext" tabindex="-1">
+              <span class="popover-title">Run uninstall lifecycle
+                operations</span> <span class="popover-content"> </span>
+          </span>
+        </span>
+      </span>
+    </span>
+    </label>
+  </div>
+  <div style="margin-top: 10px;">
+    <label for="install_first_flow" class="btn-switch-label"
+      ng-class="{'b2b-disabled-label':allDisabled}"> <input
+      type="button"
+      aria-pressed="{{ecdapp.install_first_flow_flag.value}}"
+      id="refresh_switch" b2b-switches
+      ng-model="ecdapp.install_first_flow_flag.value"
+      ng-disabled="allDisabled" aria-disabled="{{allDisabled}}"
+      aria-label="Auto-refresh is {{ecdapp.install_first_flow_flag.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}">
+      <label style="margin-left: 10px;" aria-hidden="true">Run
+        install workflow first</label> <span class="tooltip" b2b-tooltip>
+        <a href="#" class="icon-tooltip tooltip-element" tabindex="0"
+        role="button" data-placement="top" aria-label="Help"
+        aria-describedby="tooltiptextRadio"> <span class="arrow"></span>
+      </a> <span class="tooltip-wrapper"> <span
+          class="tooltip-size-control"> <span
+            id="tooltiptextRadio" role="tooltip" aria-live="polite"
+            aria-hidden="true" class="helpertext" tabindex="-1">
+              <span class="popover-title">Run install workflow
+                first, then uninstall workflow. Default: first uninstall
+                then install workflow.</span> <span class="popover-content">
+            </span>
+          </span>
+        </span>
+      </span>
+    </span>
+    </label>
+  </div>
+  <div style="margin-top: 10px;">
+    <label for="reinstall_flow" class="btn-switch-label"
+      ng-class="{'b2b-disabled-label':allDisabled}"> <input
+      type="button" aria-pressed="{{ecdapp.reinstall_flow.value}}"
+      id="refresh_switch" b2b-switches
+      ng-model="ecdapp.reinstall_flow.value" ng-disabled="allDisabled"
+      aria-disabled="{{allDisabled}}"
+      aria-label="Auto-refresh is {{ecdapp.reinstall_flow.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}">
+      <label style="margin-left: 10px;" aria-hidden="true">Run
+        automatic reinstall</label> <span class="tooltip" b2b-tooltip> <a
+        href="#" class="icon-tooltip tooltip-element" tabindex="0"
+        role="button" data-placement="top" aria-label="Help"
+        aria-describedby="tooltiptextRadio"> <span class="arrow"></span>
+      </a> <span class="tooltip-wrapper"> <span
+          class="tooltip-size-control"> <span
+            id="tooltiptextRadio" role="tooltip" aria-live="polite"
+            aria-hidden="true" class="helpertext" tabindex="-1">
+              <span class="popover-title">Automatically reinstall
+                node instances whose properties have been modified as
+                part of deployment update. If not set then, node
+                instances that were explicitly given to "Reinstall node
+                instances list" will be reinstalled.</span> <span
+              class="popover-content"> </span>
+          </span>
+        </span>
+      </span>
+    </span>
+    </label>
+  </div>
+  <div style="margin-top: 10px;">
+    <div class="field-group">
+      <div class="group">
+        <label class="col-sm-3 control-label">Reinstall node
+          instances list </label> <span class="tooltip" b2b-tooltip> <a
+          href="#" class="icon-tooltip tooltip-element" tabindex="0"
+          role="button" data-placement="top" aria-label="Help"
+          aria-describedby="tooltiptextRadio"> <span class="arrow"></span>
+        </a> <span class="tooltip-wrapper"> <span
+            class="tooltip-size-control"> <span
+              id="tooltiptextRadio" role="tooltip" aria-live="polite"
+              aria-hidden="true" class="helpertext" tabindex="-1">
+                <span class="popover-title">Node instances to be
+                  installed as part of the deployment update. They will
+                  be reinstalled even if "Run automatic reinstall" is
+                  not set</span> <span class="popover-content"> </span>
+            </span>
+          </span>
+        </span>
+        </span>
+        <ui-select multiple ng-model="ecdapp.selectedNodeInst"
+          theme="bootstrap" close-on-select="false"
+          title="node instance"> <ui-select-match
+          class="ui-select-match">{{$item}}</ui-select-match> <ui-select-choices
+          class="ui-select-choices"
+          repeat="nodeInst in ecdapp.nodeInst | filter:$select.search"
+          position='down'> {{nodeInst}} </ui-select-choices> </ui-select>
+      </div>
+    </div>
+    <div style="margin-top: 10px;">
+      <label for="force" class="btn-switch-label"
+        ng-class="{'b2b-disabled-label':allDisabled}"> <input
+        type="button" aria-pressed="{{ecdapp.force_flag.value}}"
+        id="refresh_switch" b2b-switches
+        ng-model="ecdapp.force_flag.value" ng-disabled="allDisabled"
+        aria-disabled="{{allDisabled}}"
+        aria-label="Auto-refresh is {{ecdapp.force_flag.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}">
+        <label style="margin-left: 10px;" aria-hidden="true">Force
+          update</label> <span class="tooltip" b2b-tooltip> <a href="#"
+          class="icon-tooltip tooltip-element" tabindex="0"
+          role="button" data-placement="top" aria-label="Help"
+          aria-describedby="tooltiptextRadio"> <span class="arrow"></span>
+        </a> <span class="tooltip-wrapper"> <span
+            class="tooltip-size-control"> <span
+              id="tooltiptextRadio" role="tooltip" aria-live="polite"
+              aria-hidden="true" class="helpertext" tabindex="-1">
+                <span class="popover-title">Force running update
+                  in case a previous update on this deployment has
+                  failed to finish successfully</span> <span
+                class="popover-content"> </span>
+            </span>
+          </span>
+        </span>
+      </span>
+      </label>
+    </div>
+  </div>
+  <!-- show progress indicator -->
+  <div ng-show="ecdapp.deploymentInProgress">
+    <div class="span" style="margin-bottom: 20px;">
+      <i class="icon-spinner small" role="img"
+        aria-label="Please wait while the content loads"></i> Please
+      wait while the task completes.
+    </div>
+  </div>
+  <div class="b2b-modal-footer ng-scope ng-isolate-scope">
+    <div class="cta-button-group in"
+      ng-hide="ecdapp.deploymentInProgress">
+      <button class="btn btn-alt btn-small" type="button"
+        ng-click="ecdapp.updateDeployment(ecdapp.editRequest)"
+        ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg">
+        Update</button>
+      <button class="btn btn-alt btn-small" type="button"
+        ng-click="$dismiss('cancel');">Close</button>
+    </div>
+  </div>
 </script>
 <script type="text/ng-template" id="blueprint_data_view_popup.html">
-
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content">
-
-               <!-- show progress indicator -->
-               <div ng-show="ecdapp.isDataLoading">
-                       <div class="span" style="margin-bottom:20px;">
-                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                       Please wait while the content loads.
-               </div>
-               </div>
-
-               <div ng-show="ecdapp.errMsg">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-
-                       <div class="row-nowrap">
-                       <div class="span12">
-                               <label for="typeName">Blueprint Name</label>
-                               <!--not editable-->
-                               <input id="typeName" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.typeName"/>
-                       </div>
-                       </div>
-               <div ng-hide="ecdapp.errMsg">
-                       <pre>{{ecdapp.blueprint}}</pre>
-               </div>
-
-       </div>
-
-       <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-               <div class="cta-button-group in">
-                       <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="$dismiss('cancel');">
-                               Close
-                       </button>
-               </div>
-       </div>
-
-</script>
-
-<script type="text/ng-template" id="inventory_deployment_rollback_popup.html">
-
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content">
-
-               <!-- show progress indicator -->
-               <div ng-show="ecdapp.isDataLoading">
-                       <div class="span" style="margin-bottom:20px;">
-                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                       Please wait while the content loads.
-               </div>
-               </div>
-
-               <div ng-show="ecdapp.errMsg">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-
-               <div ng-hide="ecdapp.errMsg">
-                       <div class="row-nowrap">
-                               <div class="span12">
-                                       <label for="deploymentRef">Deployment Ref</label>
-                                       <!--not editable-->
-                                       <input id="deploymentRef" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.deploymentRef"/>
-                               </div>
-                               <div class="span12">
-                                       <label for="serviceId">Service ID</label>
-                                       <!--not editable-->
-                                       <input id="serviceId" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.serviceId"/>
-                               </div> 
-                               <div class="span12">
-                                       <label for="tenantName">Tenant Name</label>
-                                       <!--not editable-->
-                                       <input id="tenantName" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.ui_tenant"/>
-                               </div> 
-                       </div>                  
-
-               <div ng-hide="ecdapp.isDataLoading">
-               <div 
-                       b2b-table 
-                       id="revisions-table"
-                       class="b2b-table-div" 
-                       table-data="ecdapp.local_revisions" >
-                       <table>    
-                           <thead b2b-table-row type="header"> 
-                                               <tr id="th-header-row">
-                                                       <th b2b-table-header>Revision</th>
-                                                       <th b2b-table-header>Updated</th>
-                                                       <th b2b-table-header>Status</th>
-                                                       <th b2b-table-header>Chart</th>
-                                                       <th b2b-table-header>Description</th>
-                                                       <th b2b-table-header sortable="false"><i class="icon-controls-gear ecd-icon-display"></i></th>
-                                               </tr>
-                                       </thead>
-                                       
-                           <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.local_revisions">
-                                               <tr id="tr-rowData">
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.revision"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.updated"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.status"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.chart"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.description"/>
-                                                       <td ng-if="!$last" b2b-table-body>
-                               <div class="form-row">
-                               <label class="checkbox">
-                               <input type="checkbox" ng-model="rowData.checked" ng-click="ecdapp.updateSelection(rowData.revision)" />
-                                                       <i class="skin"></i>
-                               </label>
-                               </div>
-                                               </td>
-                                               </tr>
-                                       </tbody>
-                               </table>
-                       </div> 
-               </div>
-       </div>
-
-       <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-               <div class="cta-button-group in">
-                       <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="ecdapp.rollbackWorkflow(ecdapp.revision);" ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg">
-                                       Start Rollback
-                       </button>
-                       <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="$dismiss('cancel');">
-                               Close
-                       </button>
-               </div>
-       </div>
-
+  <div class="b2b-modal-header ng-scope">
+    <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
+    <div class="corner-button in">
+      <button type="button" class="close" aria-label="Close"
+        ng-click="$dismiss('cancel')"></button>
+    </div>
+  </div>
+  <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+    role="region" aria-label="Modal body content">
+    <!-- show progress indicator -->
+    <div ng-show="ecdapp.isDataLoading">
+      <div class="span" style="margin-bottom: 20px;">
+        <i class="icon-spinner small" role="img"
+          aria-label="Please wait while the content loads"></i> Please
+        wait while the content loads.
+      </div>
+    </div>
+    <div ng-show="ecdapp.errMsg">
+      <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
+    </div>
+    <div class="row-nowrap">
+      <div class="span12">
+        <label for="typeName">Blueprint Name</label>
+        <!--not editable-->
+        <input id="typeName" class="span12" type="text"
+          disabled="disabled" data-ng-model="ecdapp.typeName" />
+      </div>
+    </div>
+    <div ng-hide="ecdapp.errMsg">
+      <pre>{{ecdapp.blueprint}}</pre>
+    </div>
+  </div>
+  <div class="b2b-modal-footer ng-scope ng-isolate-scope">
+    <div class="cta-button-group in">
+      <button class="btn btn-alt btn-small" type="button"
+        ng-click="$dismiss('cancel');">Close</button>
+    </div>
+  </div>
 </script>
-
-<script type="text/ng-template" id="inventory_deployment_upgrade_popup.html">
-
-       <style>
-       .ecd-parameter-table
-       {
-           border:   1px;
-       overflow: auto;
-       }
-       .ecd-parameter-table th 
-       {
-               font-size: 1.4rem;
-       }
-       </style>
-
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content">
-
-               <!-- show progress indicator -->
-               <div ng-show="ecdapp.isDataLoading">
-                       <div class="span" style="margin-bottom:20px;">
-                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                       Please wait while the content loads.
-               </div>
-               </div>
-
-               <div ng-show="ecdapp.errMsg">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-       
-               <div ng-hide="ecdapp.errMsg">
-                       <div class="row-nowrap">
-                               <div class="span12">
-                                       <label for="deploymentRef">Deployment Ref</label>
-                                       <!--not editable-->
-                                       <input id="deploymentRef" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.deploymentRef"/>
-                               </div>
-                               <div class="span12">
-                                       <label for="serviceId">Service ID</label>
-                                       <!--not editable-->
-                                       <input id="serviceId" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.serviceId"/>
-                               </div> 
-                               <div class="span12">
-                                       <label for="tenantName">Tenant Name</label>
-                                       <!--not editable-->
-                                       <input id="tenantName" class="span12" type="text" disabled="disabled" data-ng-model="ecdapp.ui_tenant"/>
-                               </div> 
-                       </div>                  
-                       
-                       <div class="row-nowrap">
-                               <div class="span12">
-                                       <div class="form-row">
-                                               <label for="parameters">*Parameters</label>
-                                               <div b2b-file-drop file-model="ecdapp.editRequest.fileModel" on-drop="handleFileSelect()" align="center">
-                                                       <span b2b-file-link file-model="ecdapp.editRequest.fileModel" on-file-select="handleFileSelect()" >
-                                                       Drag &amp; drop a parameters JSON file here, or click to browse.
-                                                               </span>
-                                       </div>
-                               </div>
-                               <div class="ecd-parameter-table">
-                                               <table id="parameters">
-                                                       <tr id="ecd-table-header">
-                                                               <th width="40%">Name</th>
-                                                               <th width="60%">Value</th>
-                                                       </tr>
-                                                       <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.resourceDefinitionChanges">
-                                                               <tr id="tr-rowData">
-                                                                       <td ng-bind="pkey"/>
-                                                                       <td>
-                                                                       <input id="parameterValue" class="span12" type="text" 
-                                                                               data-ng-model="ecdapp.editRequest.resourceDefinitionChanges[pkey]" autofocus/>
-                                                                       </td>
-                                                               </tr>
-                                                       </tbody>
-                                                       <tbody ng-repeat="(pkey, pval) in ecdapp.editRequest.resourceConstants">
-                                                               <tr id="tr-rowData">
-                                                                       <td ng-bind="pkey"/>
-                                                                       <td ng-bind="pval"/>
-                                                               </tr>
-                                                       </tbody>                        
-                                               </table>
-                                       </div>
-                               </div>
-                       </div>
-               </div>
-       </div>
-
-       <!-- show progress indicator -->
-       <div style="width: 100%;">
-               <div ng-show="ecdapp.updatingDeployment" style="display: table; margin: 0 auto;" class="span">
-               <i class="icon-spinner small" role="img" aria-label="Update Deployment in Progress..."></i>
-                       Update Deployment in Progress...
-               </div>
-       </div>
-
-       <div class="b2b-modal-footer ng-scope ng-isolate-scope" ng-show="!ecdapp.updatingDeployment">
-               <div class="cta-button-group in">
-                       <!--<div ng-show="!ecdapp.isDataLoading">-->
-                               <button class="btn btn-alt btn-small" type="button"
-                                               ng-click="ecdapp.upgradeWorkflow(ecdapp.editRequest.resourceDefinitionChanges);" ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg">
-                                       Start Upgrade
-                               </button>
-                       <!--</div>-->
-                       <button class="btn btn-small" type="button"
-                               ng-click="$dismiss('cancel')">
-                               Cancel
-                       </button>
-               </div>
-       </div>
+<script type="text/ng-template"
+  id="inventory_deployment_rollback_popup.html">
+  <div class="b2b-modal-header ng-scope">
+    <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
+    <div class="corner-button in">
+      <button type="button" class="close" aria-label="Close"
+        ng-click="$dismiss('cancel')"></button>
+    </div>
+  </div>
+  <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+    role="region" aria-label="Modal body content">
+    <!-- show progress indicator -->
+    <div ng-show="ecdapp.isDataLoading">
+      <div class="span" style="margin-bottom: 20px;">
+        <i class="icon-spinner small" role="img"
+          aria-label="Please wait while the content loads"></i> Please
+        wait while the content loads.
+      </div>
+    </div>
+    <div ng-show="ecdapp.errMsg">
+      <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
+    </div>
+    <div ng-hide="ecdapp.errMsg">
+      <div class="row-nowrap">
+        <div class="span12">
+          <label for="deploymentRef">Deployment Ref</label>
+          <!--not editable-->
+          <input id="deploymentRef" class="span12" type="text"
+            disabled="disabled" data-ng-model="ecdapp.deploymentRef" />
+        </div>
+        <div class="span12">
+          <label for="serviceId">Service ID</label>
+          <!--not editable-->
+          <input id="serviceId" class="span12" type="text"
+            disabled="disabled" data-ng-model="ecdapp.serviceId" />
+        </div>
+        <div class="span12">
+          <label for="tenantName">Tenant Name</label>
+          <!--not editable-->
+          <input id="tenantName" class="span12" type="text"
+            disabled="disabled" data-ng-model="ecdapp.ui_tenant" />
+        </div>
+      </div>
+      <div ng-hide="ecdapp.isDataLoading">
+        <div b2b-table id="revisions-table" class="b2b-table-div"
+          table-data="ecdapp.local_revisions">
+          <table>
+            <thead b2b-table-row type="header">
+              <tr id="th-header-row">
+                <th b2b-table-header>Revision</th>
+                <th b2b-table-header>Updated</th>
+                <th b2b-table-header>Status</th>
+                <th b2b-table-header>Chart</th>
+                <th b2b-table-header>Description</th>
+                <th b2b-table-header sortable="false"><i
+                  class="icon-controls-gear ecd-icon-display"></i></th>
+              </tr>
+            </thead>
+            <tbody b2b-table-row type="body"
+              row-repeat="rowData in ecdapp.local_revisions">
+              <tr id="tr-rowData">
+                <td b2b-table-body ng-bind="rowData.revision" />
+                <td b2b-table-body ng-bind="rowData.updated" />
+                <td b2b-table-body ng-bind="rowData.status" />
+                <td b2b-table-body ng-bind="rowData.chart" />
+                <td b2b-table-body ng-bind="rowData.description" />
+                <td ng-if="!$last" b2b-table-body>
+                  <div class="form-row">
+                    <label class="checkbox"> <input
+                      type="checkbox" ng-model="rowData.checked"
+                      ng-click="ecdapp.updateSelection(rowData.revision)" />
+                      <i class="skin"></i>
+                    </label>
+                  </div>
+                </td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
+    </div>
+    <div class="b2b-modal-footer ng-scope ng-isolate-scope">
+      <div class="cta-button-group in">
+        <button class="btn btn-alt btn-small" type="button"
+          ng-click="ecdapp.rollbackWorkflow(ecdapp.revision);"
+          ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg">
+          Start Rollback</button>
+        <button class="btn btn-alt btn-small" type="button"
+          ng-click="$dismiss('cancel');">Close</button>
+      </div>
+    </div>
 </script>
+<script type="text/ng-template"
+  id="inventory_deployment_upgrade_popup.html">
+    <style>
+.ecd-parameter-table {
+       border: 1px;
+       overflow: auto;
+}
+
+.ecd-parameter-table th {
+       font-size: 1.4rem;
+}
+</style>
+    <div class="b2b-modal-header ng-scope">
+      <h2 id="myModalLabel" modal-title="">{{ecdapp.label}}</h2>
+      <div class="corner-button in">
+        <button type="button" class="close" aria-label="Close"
+          ng-click="$dismiss('cancel')"></button>
+      </div>
+    </div>
+    <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+      role="region" aria-label="Modal body content">
+      <!-- show progress indicator -->
+      <div ng-show="ecdapp.isDataLoading">
+        <div class="span" style="margin-bottom: 20px;">
+          <i class="icon-spinner small" role="img"
+            aria-label="Please wait while the content loads"></i> Please
+          wait while the content loads.
+        </div>
+      </div>
+      <div ng-show="ecdapp.errMsg">
+        <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
+      </div>
+      <div ng-hide="ecdapp.errMsg">
+        <div class="row-nowrap">
+          <div class="span12">
+            <label for="deploymentRef">Deployment Ref</label>
+            <!--not editable-->
+            <input id="deploymentRef" class="span12" type="text"
+              disabled="disabled" data-ng-model="ecdapp.deploymentRef" />
+          </div>
+          <div class="span12">
+            <label for="tenantName">Tenant Name</label>
+            <!--not editable-->
+            <input id="tenantName" class="span12" type="text"
+              disabled="disabled" data-ng-model="ecdapp.ui_tenant" />
+          </div>
+        </div>
+        <div class="row-nowrap">
+          <div class="span12">
+            <div class="form-row">
+              <label for="parameters">*Parameters</label>
+              <div b2b-file-drop
+                file-model="ecdapp.editRequest.fileModel"
+                on-drop="handleFileSelect()" align="center">
+                <span b2b-file-link
+                  file-model="ecdapp.editRequest.fileModel"
+                  on-file-select="handleFileSelect()"> Drag
+                  &amp; drop a parameters JSON file here, or click to
+                  browse. </span>
+              </div>
+            </div>
+            <div class="ecd-parameter-table">
+              <table id="parameters">
+                <tr id="ecd-table-header">
+                  <th width="40%">Name</th>
+                  <th width="60%">Value</th>
+                </tr>
+                <tbody
+                  ng-repeat="(pkey, pval) in ecdapp.editRequest.resourceDefinitionChanges">
+                  <tr id="tr-rowData">
+                    <td ng-bind="pkey" />
+                    <td><input id="parameterValue" class="span12"
+                      type="text"
+                      data-ng-model="ecdapp.editRequest.resourceDefinitionChanges[pkey]"
+                      autofocus /></td>
+                  </tr>
+                </tbody>
+                <tbody
+                  ng-repeat="(pkey, pval) in ecdapp.editRequest.resourceConstants">
+                  <tr id="tr-rowData">
+                    <td ng-bind="pkey" />
+                    <td ng-bind="pval" />
+                  </tr>
+                </tbody>
+              </table>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- show progress indicator -->
+    <div style="width: 100%;">
+      <div ng-show="ecdapp.updatingDeployment"
+        style="display: table; margin: 0 auto;" class="span">
+        <i class="icon-spinner small" role="img"
+          aria-label="Update Deployment in Progress..."></i> Update
+        Deployment in Progress...
+      </div>
+    </div>
+    <div class="b2b-modal-footer ng-scope ng-isolate-scope"
+      ng-show="!ecdapp.updatingDeployment">
+      <div class="cta-button-group in">
+        <!--<div ng-show="!ecdapp.isDataLoading">-->
+        <button class="btn btn-alt btn-small" type="button"
+          ng-click="ecdapp.upgradeWorkflow(ecdapp.editRequest.resourceDefinitionChanges);"
+          ng-show="!ecdapp.isDataLoading && !ecdapp.errMsg">
+          Start Upgrade</button>
+        <!--</div>-->
+        <button class="btn btn-small" type="button"
+          ng-click="$dismiss('cancel')">Cancel</button>
+      </div>
+    </div>
+</script>
\ No newline at end of file
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_deployment_table.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/inventory/inventory_deployment_table.html
deleted file mode 100644 (file)
index 66ab9b5..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-<div id="page-content">
-
-       <h1 class="heading-page" id="deployments-page">Deployments</h1>
-
-       <!-- show progress indicator -->
-       <div ng-show="ecdapp.isDataLoading">
-               <div class="span" style="margin-bottom:20px;">
-                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                       Please wait while the content loads.
-               </div>
-       </div>
-
-       <div ng-hide="ecdapp.isDataLoading">
-               <div id="button-search-row">
-                       <div style="float:right;">
-                               <div class="group">
-                                       <button tabindex="-1" class="btn btn-small" title="Reset Filters" type="button" ng-click="ecdapp.loadTable()"><i class="icon-arrows-replay-restart"></i></button>
-                                       <input tabindex="0" class="btn btn-small" type="text" placeholder="Search Deployments" ng-model="ecdapp.searchBy"></input>
-                                       <button tabindex="1" class="btn btn-small" type="button" ng-click="ecdapp.searchTable(ecdapp.searchBy)"><i class="ion-search"></i></button>
-                               </div>
-                       </div>
-               </div>
-
-               <div ng-show="ecdapp.isRequestFailed">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-
-               <div ng-hide="ecdapp.isRequestFailed">
-                       <div
-                                       b2b-table
-                                       id="deployments-table"
-                                       class="b2b-table-div"
-                                       table-data="ecdapp.tableData"
-                                       current-page="ecdapp.currentPageIgnored"
-                                       next-sort="ecdapp.nextSortIgnored">
-                               <table>
-                                       <thead b2b-table-row type="header">
-                                       <tr id="th-header-row">
-                                               <th b2b-table-header sortable="false" key="serviceId" ng-click="ecdapp.sortTable('serviceId')">Service ID/Deployment Ref.</th>
-                                               <th b2b-table-header sortable="false" key="created" ng-click="ecdapp.sortTable('created')">Created</th>
-                                               <th b2b-table-header sortable="false" key="updated" ng-click="ecdapp.sortTable('modified')">Modified</th>
-                                               <th b2b-table-header sortable="false" key="tenant" style="background-color:#dbefef;">Tenant
-                                                               <button style="margin-bottom:-5px; box-shadow:0 0 0 0 rgba(0, 0, 0, 0.15); min-width:0;" tabindex="1" class="btn btn-small" title="Refresh Tenant and Status" type="button" ng-click="ecdapp.updateTable()">
-                                                               <i class="icon-arrows-replay-restart"></i>
-                                                               </button>
-                                                               <div ng-show="ecdapp.isSrvcDataLoading">
-                                                                       <div class="span" style="margin-bottom:5px;">
-                                                                       <i class="icon-spinner small" role="img" aria-label="Deployment Info is loading"></i>
-                                                                       Tenant and Status Info loading
-                                                                   </div>
-                                                               </div>
-                                               </th>
-                                               <th b2b-table-header sortable="false" key="status" style="background-color:#dbefef;">Install Status</th>
-                                               <th b2b-table-header sortable="false" style="background-color:#dbefef;">Actions</th>
-                                       </tr>
-                                       </thead>
-
-                                       <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData">
-                                       <tr id="tr-rowData">
-                                               <td b2b-table-body
-                                                       ng-bind="rowData.serviceId" 
-                                                       ng-class="{'td-error' : rowData.statusInfo === undefined}"/>
-                                               <td b2b-table-body
-                                                       ng-bind="rowData.created | date : 'MM-dd-yyyy HH:mm:ss Z'"
-                                                       ng-class="{'td-error' : rowData.statusInfo === undefined}"/>
-                                               <td b2b-table-body
-                                                       ng-bind="rowData.modified | date : 'MM-dd-yyyy HH:mm:ss Z'" 
-                                                       ng-class="{'td-error' : rowData.statusInfo === undefined}"/>
-                                               <td b2b-table-body
-                                                       ng-bind="rowData.statusInfo.tenant_name"
-                                                       ng-class="{'td-error' : rowData.statusInfo === undefined}"/>
-                                               <td b2b-table-body 
-                                                       ng-class="{'td-error' : rowData.statusInfo === undefined}">
-                                                       <img ng-src="{{rowData.statusInfo.statusImg}}" title="{{rowData.statusInfo.status}}" />
-                                                       </span>                                                                                 
-                                               </td>
-                                               <td b2b-table-body ng-class="{'td-error' : rowData.statusInfo === undefined}">
-                                                       <div class="btn-group btn-actions" style="margin-bottom:0;box-shadow:none;">
-                                                                       <button type="button" class="btn dropdown-toggle" data-toggle="dropdown" title="More Actions"><i class="icon-apps-marketplace"></i></button>                                                                    
-                                                                               <ul class="dropdown-menu">
-                                                                               <li>
-                                                                                       <div ng-click="ecdapp.viewBlueprintDataModal(rowData);">
-                                                                                                       <i class="icon-documents-book ecd-icon-action"></i><a href="">View blueprint</a>
-                                                                                               </div>
-                                                                                       </li>
-                                                                                       <li>
-                                                                                               <div ng-click="ecdapp.viewDeploymentInputsModalPopup(rowData);">
-                                                                                                       <i class="icoDocuments-report ecd-icon-action"></i><a href="">View Inputs</a>
-                                                                                               </div>
-                                                                                       </li>
-                                                                                       <li>
-                                                                                               <div ng-click="ecdapp.viewDeploymentExecutionsModalPopup(rowData);">
-                                                                                                       <i class="icon-overview ecd-icon-action"></i><a href="">View executions</a>
-                                                                                               </div>
-                                                                                       </li>
-                                                                                       <li>
-                                                                                               <div ng-show="rowData.canDeploy && rowData.statusInfo.status === 'completed'" ng-click="ecdapp.updateDeploymentModalPopup(rowData);">
-                                                                                                       <i class="icon-misc-pen ecd-icon-action"></i><a href="">Update deployment</a>
-                                                                                               </div>
-                                                                                       </li>
-                                                                                       <li>
-                                                                                               <div ng-show="rowData.canDeploy" ng-click="ecdapp.deleteDeploymentModalPopup(rowData);">
-                                                                                                       <i class="icon-misc-trash ecd-icon-action"></i><a href="">Undeploy</a>
-                                                                                               </div>
-                                                                                       </li>
-                                                                                       <li>
-                                                                                               <div ng-show="rowData.statusInfo.is_helm && rowData.statusInfo.helm_status && rowData.statusInfo.status === 'completed'" ng-click="ecdapp.checkHelmStatus(rowData);">
-                                                                                                       <i class="icoDocuments-report ecd-icon-action"></i><a href="">Helm Status</a>
-                                                                                               </div>
-                                                                                       </li>
-                                                                                       <li>
-                                                                                               <div ng-show="rowData.canDeploy && rowData.statusInfo.is_helm && rowData.statusInfo.status === 'completed'" ng-click="ecdapp.upgradeDeploymentModalPopup(rowData);">
-                                                                                                       <i class="icon-controls-down ecd-icon-action"></i><a href="#">Helm upgrade deployment</a>
-                                                                                               </div>
-                                                                                       </li>
-                                                                                       <li>
-                                                                                               <div ng-show="rowData.canDeploy && rowData.statusInfo.is_helm && rowData.statusInfo.status === 'completed'" ng-click="ecdapp.rollbackDeploymentModalPopup(rowData);">
-                                                                                                       <i class="icon-controls-up"></i><a href="#">Helm rollback deployment</a>
-                                                                                               </div>
-                                                                                       </li>
-                                                                                       <li>
-                                                                                               <div ng-show="rowData.canDeploy  && rowData.statusInfo === undefined" ng-click="ecdapp.deleteServiceModalPopup(rowData);">
-                                                                                                       <i class="icon-misc-trash ecd-icon-action"></i><a href="">Delete Service</a>
-                                                                                               </div>          
-                                                                                       </li>
-                                                                               </ul>
-                                                       </div><!-- .btn-group -->
-                                               </td>
-                                       </tr>
-                                       </tbody>
-                               </table>
-                       </div>
-
-                       <div b2b-pagination="" total-pages="ecdapp.totalPages"
-                                current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler"
-                                role="navigation">
-                       </div>
-
-               </div>
-       </div>
-
-       <div style="height: 10px;">
-               <!-- space between page number and black footer -->
-       </div>
-
-</div><!-- loading -->
-
-</div><!-- page content -->
index 4b870dc..6277207 100644 (file)
 <script type="text/ng-template" id="inventory_execution_view_popup.html">
-       <div class="b2b-modal-header ng-scope">
-               <h2 id="myModalLabel" style="margin-left: 200px;" modal-title="">{{ecdapp.label}}</h2>
-               <div class="corner-button in">
-                       <button type="button" class="close" aria-label="Close"
-                               ng-click="$dismiss('cancel')"></button>
-               </div>
-               <div style="position: absolute;">
-               <label for="show-menu" class="show-menu" title="click to view more info">&#9776;</label>
-               <input type="checkbox" id="show-menu" />
-               <div class="menu" ng-hide="ecdapp.errMsg">
-                       <!--<div class="row-nowrap" style="margin-bottom:10px;"> -->
-                               <div class="span12" style="margin-bottom:10px;">
-                                       <label for="deploymentRef">Deployment Ref</label>
-                                       <!--not editable-->
-                                       <input id="deploymentRef" class="span6" type="text" data-ng-model="ecdapp.deplRef"/>
-                               </div>
-                               <div class="span12" style="margin-bottom:10px;">
-                                       <label for="tenant">Tenant</label>
-                                       <!--not editable-->
-                                       <input id="tenant" class="span6" type="text" data-ng-model="ecdapp.ui_tenant"/>
-                               </div>
-                               <!-- <button ng-click="ecdapp.toggleStatusDefinitions()" class="btn btn-alt btn-small">Click to view status definitions</button> -->
-                                       <div>
-                                               <div b2b-table id="status-table" class="b2b-table-div">
-                                                       <table id="status-definition-table">
-                                                               <thead b2b-table-row type="header">
-                                                                       <tr id="th-header-row">
-                                                                               <th b2b-table-header key="status">Status</th>
-                                                                               <th b2b-table-header key="definition">Definition</th>
-                                                                       </tr>
-                                                               </thead>
-                                                               <tbody b2b-table-row type="body">
-                                                                       <tr>
-                                                                               <td>waiting to start</td>
-                                                                               <td>The execution is waiting for a worker to start it</td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td>in progress</td>
-                                                                               <td>The execution is currently running.</td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td>cancel in progress</td>
-                                                                               <td>The execution is currently being cancelled.</td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td>force-cancelling in progress</td>
-                                                                               <td>The execution is currently being force-cancelled.</td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td>cancelled</td>
-                                                                               <td>The execution has been cancelled.</td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td>successful</td>
-                                                                               <td>The execution has terminated successfully.</td>
-                                                                       </tr>
-                                                                       <tr>
-                                                                               <td>failed</td>
-                                                                               <td>The execution has failed. Click on the button in the error column to view the error details.</td>
-                                                                       </tr>
-                                                               </tbody>
-                                                       </table>
-                                               </div>
-                                       </div>
-               </div>
-       </div>
-       </div>
-
-       <div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
-               role="region" aria-label="Modal body content">
-
-               <!--<h1 class="heading-page" id="executions-page">Executions</h1> -->
-
-               <!-- show progress indicator -->
-               <div ng-show="ecdapp.isDataLoading">
-                       <div class="span" style="margin-bottom:20px;">
-                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                       Please wait while the content loads.
-               </div>
-               </div>
-               <div ng-show="ecdapp.isCancelOn">
-                       <div class="span" style="margin-bottom:20px;">
-                       <i class="icon-spinner small" role="img" aria-label="Cancel in progress"></i>
-                       Cancel in progress
-               </div>
-               </div>
-               <div ng-show="ecdapp.errMsg">
-                       <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
-               </div>
-               <div ng-show="ecdapp.evtErrMsg">
-                       <span class="ecd-error-message">{{ecdapp.evtErrMsg}}</span>
-               </div>
-
-    <div class="form-row" style="margin-top:0px;">
-               <div style="float: left; width: 200px; margin-left: 30px;" title="switch to enable/disable screen refresh">
-               <label for="refresh_switch" class="btn-switch-label" ng-class="{'b2b-disabled-label':allDisabled}">
-            <span aria-hidden="true">Auto-refresh</span>
-            <input type="button" aria-pressed="{{ecdapp.refresh_switch.value}}" id="refresh_switch" b2b-switches ng-model="ecdapp.refresh_switch.value" ng-disabled="allDisabled" aria-disabled="{{allDisabled}}" aria-label="Auto-refresh is {{ecdapp.refresh_switch.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}">
-               </label>
-               </div>
-        <div style="float: right;" title="Checkbox to view latest execution workflow only">
-               <label for="checkbox1" class="checkbox">
-                    <input id="checkbox1" type="checkbox" ng-model="ecdapp.isLastExecution"><i class="skin"></i><span>Last execution</span>
-            </label>
-       </div>
+<div class="b2b-modal-header ng-scope">
+  <h2 id="myModalLabel" modal-title="">
+    Deployment <span style="font-weight: bolder; background: aqua;">{{ecdapp.deplRef}}</span>
+    Executions
+  </h2>
+  <div class="corner-button in">
+    <button type="button" class="close" aria-label="Close"
+      ng-click="$dismiss('cancel')"></button>
+  </div>
+  <div style="position: absolute; right: 50px; top: 40px;">
+    <label for="show-menu" class="show-menu"
+      title="click to view more info">&#9776;</label> <input
+      type="checkbox" id="show-menu" />
+    <div class="menu" ng-hide="ecdapp.errMsg">
+      <div class="span12" style="margin-bottom: 10px;">
+        <label for="tenant">Tenant</label>
+        <!--not editable-->
+        <input id="tenant" class="span6" type="text"
+          data-ng-model="ecdapp.ui_tenant" />
+      </div>
+      <div>
+        <div b2b-table id="status-table" class="b2b-table-div">
+          <table id="status-definition-table">
+            <thead b2b-table-row type="header">
+              <tr id="th-header-row">
+                <th b2b-table-header key="status">Status</th>
+                <th b2b-table-header key="definition">Definition</th>
+              </tr>
+            </thead>
+            <tbody b2b-table-row type="body">
+              <tr>
+                <td>waiting to start</td>
+                <td>The execution is waiting for a worker to start
+                  it</td>
+              </tr>
+              <tr>
+                <td>in progress</td>
+                <td>The execution is currently running.</td>
+              </tr>
+              <tr>
+                <td>cancel in progress</td>
+                <td>The execution is currently being cancelled.</td>
+              </tr>
+              <tr>
+                <td>force-cancelling in progress</td>
+                <td>The execution is currently being
+                  force-cancelled.</td>
+              </tr>
+              <tr>
+                <td>cancelled</td>
+                <td>The execution has been cancelled.</td>
+              </tr>
+              <tr>
+                <td>successful</td>
+                <td>The execution has terminated successfully.</td>
+              </tr>
+              <tr>
+                <td>failed</td>
+                <td>The execution has failed. Click on the button
+                  in the error column to view the error details.</td>
+              </tr>
+            </tbody>
+          </table>
+        </div>
+      </div>
     </div>
-
-               <div ng-hide="ecdapp.errMsg">
-                       <div 
-                       b2b-table 
-                       id="executions-table"
-                       class="b2b-table-div" 
-                       table-data="ecdapp.tableData" 
-                       search-string="ecdapp.searchString" 
-                       current-page="ecdapp.currentPageIgnored"
-                       next-sort="ecdapp.nextSortIgnored">
-
-                       <table>
-                           <thead b2b-table-row type="header"> 
-                                               <tr id="th-header-row">
-                                                       <th b2b-table-header key="created_at">Created Date</th>
-                                                       <th b2b-table-header key="workflow_id">Workflow ID</th>
-                                                       <th b2b-table-header key="id">ID</th>
-                                                       <th b2b-table-header key="status">Status</th>
-                                                       <th b2b-table-header sortable="false"><i class="icon-settings ecd-icon-display"></i></th>
-                                               </tr>
-                                       </thead>
-                                       
-                           <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.tableData">
-                                               <tr id="tr-rowData">
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.created_at"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.workflow_id"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.id"/>
-                                                       <td b2b-table-body ng-if="rowData.status == 'pending'">
-                                                               waiting to start
-                                                       </td>
-                                                       <td b2b-table-body ng-if="rowData.status == 'started'">
-                                                       <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);">
-                                                               <a href="" title="View execution logs" class="tooltip">in progress</a>
-                                                       </div>
-                                                       </td>
-                                                       <td b2b-table-body ng-if="rowData.status == 'cancelling'">
-                                                       <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);">
-                                                               <a href="" title="View execution logs" class="tooltip">cancel in progress</a>
-                                                       </div>  
-                                                       </td>
-                                                       <td b2b-table-body ng-if="rowData.status == 'force_cancelling'">
-                                                               <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);">
-                                                               <a href="" title="View execution logs" class="tooltip">force-cancelling in progress</a>
-                                                       </div>                          
-                                                       </td>
-                                                       <td b2b-table-body ng-if="rowData.status == 'cancelled'">
-                                                               <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);">
-                                                               <a href="" title="View execution logs" class="tooltip">cancelled</a>
-                                                       </div>
-                                                       </td>
-                                                       <td b2b-table-body ng-if="rowData.status == 'terminated'">
-                                                       <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);">
-                                                               <a href="" title="View execution logs" class="tooltip">successful</a>
-                                                       </div>
-                                                       </td>
-                                                       <td b2b-table-body ng-if="rowData.status == 'failed'">
-                                                       <div ng-click="ecdapp.getExecutionLogs(rowData.id, ecdapp.ui_tenant);">
-                                                               <a href="" title="View execution logs" class="tooltip">failed</a>
-                                                       </div>
-                                                       </td>
-                                                       <td b2b-table-body ng-if="rowData.status == 'failed'">
-                                                       <div ng-show="rowData.error" ng-click="ecdapp.viewErrorModalPopup(rowData);">
-                                                               <a href="" title="View error details" class="icon-people-preview ecd-icon-action"></a>
-                                                       </div>
-                                               </td>
-                                                       <td b2b-table-body ng-if="rowData.status == 'started'"> 
-                                                       <div ng-click="ecdapp.cancelExecutionModalPopup(rowData, ecdapp.ui_tenant);">
-                                                                       <a href="" title="Cancel execution" class="ion-stop ecd-icon-action"></a>
-                                                       </div>
-                                               </td>
-                                               </tr>
-                                       </tbody>
-                               </table>
-                       </div> 
-                       <!-- <div b2b-pagination="" total-pages="ecdapp.totalPages" 
-                                               current-page="ecdapp.currentPageNum" click-handler="pageChangeHandler"
-                                               role="navigation">
-                       </div> -->
-                       </div>
-                       <div ng-show="ecdapp.isEventLogQuery">
-                               <div style="float: left;">
-                                       <h3>Events/Logs </h3>
-                                       <h4>execution id: {{ecdapp.executionId}} </h4>
-                               </div>
-                       <div style="float: right;" title="Checkbox to Include log type events">
-                               <label for="checkbox2" class="checkbox">
-                    <input id="checkbox2" type="checkbox" ng-model="ecdapp.isLogType"><i class="skin"></i><span>Include Logs</span>
-                       </label>
-                               </div>
-
-                               <div 
-                       b2b-table 
-                       id="logs-table"
-                       class="b2b-table-div" 
-                       table-data="ecdapp.logTableData"
-                       current-page="ecdapp.currentPageIgnored"
-                       next-sort="ecdapp.nextSortIgnored">
-                       <table>
-                           <thead b2b-table-row type="header"> 
-                                               <tr id="th-header-row">
-                                                       <th b2b-table-header key="reported_timestamp">Reported Timestamp</th>
-                                                       <th b2b-table-header key="timestamp">Type</th>
-                                                       <th b2b-table-header key="event_type">Event Type</th>
-                                                       <th b2b-table-header key="message">Message</th>
-                                                       <th b2b-table-header key="node_name">Node name</th>
-                                                       <th b2b-table-header key="node_instance_id">Node Instance</th>
-                                                       <th b2b-table-header key="error_causes">Error Causes</th>
-                                               </tr>
-                                       </thead>                        
-                           <tbody b2b-table-row type="body" row-repeat="rowData in ecdapp.logTableData">
-                                               <tr id="tr-rowData" ng-class="{ 'red-background' : rowData.message.toLowerCase().contains("error") }">
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.reported_timestamp"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.type"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.event_type"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.message"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.node_name"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.node_instance_id"/>
-                                                       <td b2b-table-body
-                                                               ng-bind="rowData.error_causes[0].traceback"/>
-                                               </tr>
-                                       </tbody>
-                       </table>
-                       </div>
-                       <div b2b-pagination="" total-pages="ecdapp.totalLogPages" 
-                                               current-page="ecdapp.currentLogPageNum" click-handler="pageChangeHandler"
-                                               role="navigation">
-                       </div>
-               </div>
-
-       <div class="b2b-modal-footer ng-scope ng-isolate-scope">
-               <div class="cta-button-group in">
-                       <button class="btn btn-alt btn-small" type="button"
-                                       ng-click="$dismiss('cancel');">
-                               Close
-                       </button>
-               </div>
-       </div>
-
+  </div>
+</div>
+<div class="b2b-modal-body ng-scope ng-isolate-scope" tabindex="0"
+  role="region" aria-label="Modal body content">
+  <!--<h1 class="heading-page" id="executions-page">Executions</h1> -->
+  <!-- show progress indicator -->
+  <div ng-show="ecdapp.isDataLoading">
+    <div class="span" style="margin-bottom: 20px;">
+      <i class="icon-spinner small" role="img"
+        aria-label="Please wait while the content loads"></i> Please
+      wait while the content loads.
+    </div>
+  </div>
+  <div ng-show="ecdapp.isCancelOn">
+    <div class="span" style="margin-bottom: 20px;">
+      <i class="icon-spinner small" role="img"
+        aria-label="Cancel in progress"></i> Cancel in progress
+    </div>
+  </div>
+  <div ng-show="ecdapp.errMsg">
+    <span class="ecd-error-message">{{ecdapp.errMsg}}</span>
+  </div>
+  <div ng-show="ecdapp.evtErrMsg">
+    <span class="ecd-error-message">{{ecdapp.evtErrMsg}}</span>
+  </div>
+  <div class="form-row" style="margin-top: 0px;">
+    <div style="float: left; width: 200px; margin-left: 30px;"
+      title="switch to enable/disable screen refresh">
+      <label for="refresh_switch" class="btn-switch-label"
+        ng-class="{'b2b-disabled-label':allDisabled}"> <span
+        aria-hidden="true">Auto-refresh</span> <input type="button"
+        aria-pressed="{{ecdapp.refresh_switch.value}}"
+        id="refresh_switch" b2b-switches
+        ng-model="ecdapp.refresh_switch.value" ng-disabled="allDisabled"
+        aria-disabled="{{allDisabled}}"
+        aria-label="Auto-refresh is {{ecdapp.refresh_switch.value?'On':'Off'}}. {{allDisabled?'Disabled. Explanation why it is disabled':''}}">
+      </label>
+    </div>
+    <div style="float: right;"
+      title="Checkbox to view latest execution workflow only">
+      <label for="checkbox1" class="checkbox"> <input
+        id="checkbox1" type="checkbox" ng-model="ecdapp.isLastExecution"><i
+        class="skin"></i><span>Last execution</span>
+      </label>
+    </div>
+  </div>
+  <div ng-hide="ecdapp.errMsg">
+    <div b2b-table id="executions-table" class="b2b-table-div"
+      table-data="ecdapp.tableData" search-string="ecdapp.searchString"
+      current-page="ecdapp.currentPageIgnored"
+      next-sort="ecdapp.nextSortIgnored">
+      <table>
+        <thead b2b-table-row type="header">
+          <tr id="th-header-row">
+            <th b2b-table-header key="index">#</th>
+            <th b2b-table-header key="created_at">Created Date</th>
+            <th b2b-table-header key="workflow_id">Workflow ID</th>
+            <th b2b-table-header key="id">ID</th>
+            <th b2b-table-header key="status">Status</th>
+            <th b2b-table-header sortable="false">Actions<i
+              class="icon-controls-gear ecd-icon-display"></i></th>
+          </tr>
+        </thead>
+        <tbody b2b-table-row type="body"
+          ng-repeat="rowData in ecdapp.tableData"
+          ng-class="{'selected':$index == ecdapp.selectedRow}">
+          <!--ng-click="ecdapp.setClickedRow($index)" -->
+          <tr id="tr-rowData">
+            <td b2b-table-body>{{$index+1}}</td>
+            <td b2b-table-body ng-bind="rowData.created_at" />
+            <td b2b-table-body ng-bind="rowData.workflow_id" />
+            <td b2b-table-body ng-bind="rowData.id" />
+            <td b2b-table-body ng-if="rowData.status == 'pending'">
+              waiting to start</td>
+            <td b2b-table-body ng-if="rowData.status == 'started'">
+              <div
+                ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);">
+                <a href="" title="View execution logs" class="tooltip">in
+                  progress</a>
+              </div>
+            </td>
+            <td b2b-table-body ng-if="rowData.status == 'cancelling'">
+              <div
+                ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);">
+                <a href="" title="View execution logs" class="tooltip">cancel
+                  in progress</a>
+              </div>
+            </td>
+            <td b2b-table-body
+              ng-if="rowData.status == 'force_cancelling'">
+              <div
+                ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);">
+                <a href="" title="View execution logs" class="tooltip">force-cancelling
+                  in progress</a>
+              </div>
+            </td>
+            <td b2b-table-body ng-if="rowData.status == 'cancelled'">
+              <div
+                ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);">
+                <a href="" title="View execution logs" class="tooltip">cancelled</a>
+              </div>
+            </td>
+            <td b2b-table-body ng-if="rowData.status == 'terminated'">
+              <div
+                ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);">
+                <a href="" title="View execution logs" class="tooltip">successful</a>
+              </div>
+            </td>
+            <td b2b-table-body ng-if="rowData.status == 'failed'">
+              <div
+                ng-click="ecdapp.getExecutionLogs($index, rowData.id, ecdapp.ui_tenant);">
+                <a href="" title="View execution logs" class="tooltip">failed</a>
+              </div>
+            </td>
+            <td b2b-table-body ng-if="rowData.status == 'failed'">
+              <div ng-show="rowData.error"
+                ng-click="ecdapp.viewErrorModalPopup(rowData);">
+                <a href="" title="View error details"
+                  class="icon-people-preview ecd-icon-action"></a>
+              </div>
+            </td>
+            <td b2b-table-body ng-if="rowData.status == 'started'">
+              <div
+                ng-click="ecdapp.cancelExecutionModalPopup(rowData, ecdapp.ui_tenant);">
+                <a href="" title="Cancel execution"
+                  class="icon-controls-stop ecd-icon-action"></a>
+              </div>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+    <div b2b-pagination="" total-pages="ecdapp.totalPages"
+      current-page="ecdapp.currentPageNum"
+      click-handler="pageChangeHandler" role="navigation"></div>
+  </div>
+  <div ng-show="ecdapp.isEventLogQuery">
+    <div style="float: left;">
+      <h3>Events/Logs</h3>
+      <h4>execution id: {{ecdapp.execId}}</h4>
+    </div>
+    <div style="float: right;"
+      title="Checkbox to Include log type events">
+      <label for="checkbox2" class="checkbox"> <input
+        id="checkbox2" type="checkbox" ng-model="ecdapp.isLogType"><i
+        class="skin"></i><span>Include Logs</span>
+      </label>
+    </div>
+    <div b2b-table id="logs-table" class="b2b-table-div"
+      table-data="ecdapp.logTableData"
+      current-page="ecdapp.currentPageIgnored"
+      next-sort="ecdapp.nextSortIgnored">
+      <table>
+        <thead b2b-table-row type="header">
+          <tr id="th-header-row">
+            <th b2b-table-header key="reported_timestamp">Reported
+              Timestamp</th>
+            <th b2b-table-header key="timestamp">Type</th>
+            <th b2b-table-header key="event_type">Event Type</th>
+            <th b2b-table-header key="message">Message</th>
+            <th b2b-table-header key="node_name">Node name</th>
+            <th b2b-table-header key="node_instance_id">Node
+              Instance</th>
+            <th b2b-table-header key="error_causes">Error Causes</th>
+          </tr>
+        </thead>
+        <tbody b2b-table-row type="body"
+          row-repeat="rowData in ecdapp.logTableData">
+          <tr id="tr-rowData" ng-style="{'background-color':rowData.event_type === 'task_failed' 
+                       || rowData.event_type === 'workflow_failed' ? '#fbbbbb' : '#ffffff'}">
+            <td b2b-table-body ng-bind="rowData.reported_timestamp" />
+            <td b2b-table-body ng-bind="rowData.type" />
+            <td b2b-table-body ng-bind="rowData.event_type" />
+            <td b2b-table-body>
+              <div class="my-tooltip">
+                {{rowData.message | limitTo: 1000}}
+                <div class="wrapper">
+                  <div class="clip-btn-div">
+                    <button style="border-radius: 5px;margin-top: -20px;"
+                      ng-click="ecdapp.copyStringToClipboard(rowData.message)">Copy Message</button>
+                  </div>
+                  <span class="my-tooltiptext">{{rowData.message}}</span>
+                </div>
+              </div>
+            </td>
+            <td b2b-table-body ng-bind="rowData.node_name" />
+            <td b2b-table-body ng-bind="rowData.node_instance_id" />
+            <td b2b-table-body
+              ng-bind="rowData.error_causes[0].traceback" />
+          </tr>
+        </tbody>
+      </table>
+    </div>
+    <div b2b-pagination="" total-pages="ecdapp.totalLogPages"
+      current-page="ecdapp.currentLogPageNum"
+      click-handler="pageChangeHandlerEvent" role="navigation"></div>
+  </div>
+  <div class="b2b-modal-footer ng-scope ng-isolate-scope">
+    <div class="cta-button-group in">
+      <button class="btn btn-alt btn-small" type="button"
+        ng-click="$dismiss('cancel');">Close</button>
+    </div>
+  </div>
 </script>
\ No newline at end of file
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/dbcl_view.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/dbcl_view.html
deleted file mode 100644 (file)
index da9fb74..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<div id="page-content" ng-controller="tabsController">
-       <h1> DMaap Bus Controller</h1>
-               <iframe  scrolling="yes" frameborder="0" style="width:100%; height: 800px;" 
-               ng-src="{{opsMenu[5].url}}">
-       </iframe>
-</div>
\ No newline at end of file
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs-view-controller.js b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs-view-controller.js
deleted file mode 100644 (file)
index f37a4f0..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-appDS2.controller('tabsController', function ($rootScope, $scope, $interval, b2bDOMHelper, $timeout, $route) {
-       'use strict';
-       $scope.ecdapp = {};
-       $scope.ecdapp.opsItem = $route.current.$$route.item;
-       $scope.ecdapp.activeTabsId = $scope.ecdapp.opsItem ;
-       $scope.ecdapp.activeTabUrl = '';
-       $scope.ecdapp.isInit = false;
-    $scope.ecdapp.cfy = {};
-    $scope.ecdapp.cfy.url = ''; //$rootScope.opsMenu[0].url;
-    $scope.ecdapp.cfy.site = '';
-    $scope.ecdapp.cnsl = {};
-    $scope.ecdapp.cnsl.url = ''; //$rootScope.opsMenu[2].url;  
-    $scope.ecdapp.k8 = {};
-    $scope.ecdapp.k8.site = '';
-    $scope.ecdapp.k8.url = ''; //$rootScope.opsMenu[3].url;
-    $scope.ecdapp.k8.tenant = '';
-    $scope.ecdapp.prom = {};
-    $scope.ecdapp.prom.tenant = '';
-    $scope.ecdapp.prom.site = '';
-    $scope.ecdapp.prom.url = ''; //$rootScope.opsMenu[4].url;
-    $scope.ecdapp.grf = {};
-    $scope.ecdapp.grf.site = '';
-    $scope.ecdapp.grf.tenant = '';
-    $scope.ecdapp.grf.url = ''; //$rootScope.opsMenu[1].url;
-    $scope.ecdapp.isFrameLoaded = true;
-    $scope.ecdapp.cfySite = '';
-    $scope.ecdapp.cnslSite = '';
-    $scope.ecdapp.appCluster = '';
-    $scope.ecdapp.k8.cluster = '';
-    $scope.ecdapp.grf.cluster = '';
-    $scope.ecdapp.prom.cluster = '';
-    
-       var key = $scope.ecdapp.opsItem;
-       
-    // if it's not already part of our keys array
-       if($rootScope.menuKeys.indexOf(key) === -1) {
-        // add it to our keys array
-               $rootScope.menuKeys.push(key);
-               for (var itemTab = 0; itemTab < $rootScope.opsMenu.length; itemTab++) {
-                       if ($rootScope.opsMenu[itemTab].id === key) {
-                               $rootScope.gTabs.push($rootScope.opsMenu[itemTab]);
-                               //$scope.ecdapp.activeTabUrl = $rootScope.opsMenu[itemTab].url;
-                               break;
-                       }
-               }
-       }
-    $scope.ecdapp.gTabs = $rootScope.gTabs;
-       /*
-    angular.forEach($rootScope.opsMenu, function(item) {
-       if 
-                // we check to see whether our object exists
-       var key = $scope.ecdapp.opsItem;
-                // if it's not already part of our keys array
-        if($rootScope.menuKeys.indexOf(key) === -1) {
-                    // add it to our keys array
-               $rootScope.menuKeys.push(key); 
-                    // push this item to our final output array
-            $rootScope.gTabs.push(item);
-            $scope.ecdapp.activeTabUrl = item.url;
-        } else {
-               if (item.id === key) {
-                       $scope.ecdapp.activeTabUrl = item.url;
-               }
-        }
-    });
-
-
-       for (var menuTab = 0; menuTab < $scope.ecdapp.gTabs.length; menuTab++) {
-               if ($scope.ecdapp.gTabs[menuTab].id === key) {
-                       $scope.ecdapp.activeTabUrl = $scope.ecdapp.gTabs[menuTab].url;
-                       break;
-               }
-       }
-           */
-    $scope.ecdapp.isInit = true;
-    $rootScope.activeTabsId = $scope.ecdapp.opsItem;
-    
-       $rootScope.$watch('activeTabsId', function (newVal, oldVal) {           
-        if(newVal !== oldVal) {
-            var selectedTab;
-            for (selectedTab = 0; selectedTab < $rootScope.opsMenu.length; selectedTab++) {
-                if ($rootScope.opsMenu[selectedTab].id === newVal) {
-                       //$scope.ecdapp.activeTabUrl = $rootScope.opsMenu[selectedTab].url;
-                    break;
-                }
-            }
-            var selectedTabPanelElement = document.getElementById($rootScope.opsMenu[selectedTab].tabPanelId);
-
-            var elem = null;
-            if (selectedTabPanelElement) {
-                elem = b2bDOMHelper.firstTabableElement(selectedTabPanelElement);
-            }
-
-            if (elem) {
-                $timeout(function () {
-                    elem.focus();
-                }, 100);
-            }
-        }
-       });
-       
-
-       $scope.ecdapp.selectAppTenant = function(site) {
-               if(site != "Select Site") {
-                       for (var indx = 0; indx < $rootScope.site_tenant_map.length; indx++) {
-                               if ($rootScope.site_tenant_map[indx].site === site) {
-                                       $scope.ecdapp.appTenants = $rootScope.site_tenant_map[indx].tenant;
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       $scope.ecdapp.selectCluster = function(tenant) {
-               if(tenant != "Select Tenant") {
-                       for (var indx = 0; indx < $rootScope.tenant_cluster_map.length; indx++) {
-                               if ($rootScope.tenant_cluster_map[indx].tenant === tenant) {
-                                       $scope.ecdapp.appCluster = $rootScope.tenant_cluster_map[indx].cluster;
-                               }
-                       }
-               }
-       }
-       
-       var stopPolling;
-        //var doIframePolling;
-       $scope.ecdapp.appFrameReload = function(cluster, app) {
-               if(cluster != "Select K8s cluster") {
-                       $scope.ecdapp.isFrameLoaded = false;
-                       for (var indx = 0; indx < $rootScope.tenant_cluster_apps_map.length; indx++) {
-                               if ($rootScope.tenant_cluster_apps_map[indx].cluster === cluster) {
-                                       if (app === 'prom') {
-                                       $scope.ecdapp.prom.url = $rootScope.tenant_cluster_apps_map[indx].prom;
-                                       } else if (app === 'grf') {
-                                       $scope.ecdapp.grf.url = $rootScope.tenant_cluster_apps_map[indx].grf;
-                                       } else {
-                                       $scope.ecdapp.k8.url = $rootScope.tenant_cluster_apps_map[indx].k8;
-                                       }
-                                       break;
-                               }
-                       }
-                       stopPolling = $timeout(function () {
-                       $timeout.cancel(stopPolling);
-                       stopPolling = undefined;
-                       $scope.ecdapp.isFrameLoaded = true;     
-                       },30000);
-                       }
-       }
-       
-       $scope.ecdapp.cfyCnslFrameReload = function(site, app) {
-               if(site != "Select Site") {
-                       $scope.ecdapp.isFrameLoaded = false;
-                       for (var indx = 0; indx < $rootScope.site_cfy_cnsl_map.length; indx++) {
-                               if ($rootScope.site_cfy_cnsl_map[indx].site === site) {
-                                       if (app === 'cfy') {
-                                               $scope.ecdapp.cfy.url = $rootScope.site_cfy_cnsl_map[indx].cfy;
-                                       } else {
-                                               $scope.ecdapp.cnsl.url = $rootScope.site_cfy_cnsl_map[indx].cnsl;
-                                       }
-                                       break;
-                               }
-                       }
-                       stopPolling = $timeout(function () {
-                       $timeout.cancel(stopPolling);
-                       stopPolling = undefined;
-                       $scope.ecdapp.isFrameLoaded = true;     
-                       },30000);
-               }
-       }
-       document.querySelector("iframe").addEventListener("load", function() {
-                       $scope.ecdapp.isFrameLoaded = true;
-                       $scope.$apply();
-               });
-        $scope.$on("$destroy",function() {
-               $timeout.cancel(stopPolling);
-               //$interval.cancel(doIframePolling);
-        });
-        
-               /*
-                *      $scope.ecdapp.selectK8Tenant = function(site) {
-                       if(site != "Select Site") {
-                               for (var indx = 0; indx < $rootScope.site_tenant_map.length; indx++) {
-                                       if ($rootScope.site_tenant_map[indx].site === site) {
-                                               $scope.ecdapp.k8Tenants = $rootScope.site_tenant_map[indx].tenant;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               
-               $scope.ecdapp.selectK8App = function(t) {
-                       if(t != "Select Tenant for K8s components") {
-                       for (var indx = 0; indx < $rootScope.tenant_cluster_map.length; indx++) {
-                               if ($rootScope.tenant_cluster_map[indx].tenant === t) {
-                                       $scope.ecdapp.k8.url = $rootScope.tenant_cluster_map[indx].k8s;
-                                       break;
-                               }
-                       }
-                       }
-               }
-
-               $scope.ecdapp.selectGrfTenant = function(site) {
-                       if(site != "Select Site") {
-                       for (var indx = 0; indx < $rootScope.site_tenant_map.length; indx++) {
-                               if ($rootScope.site_tenant_map[indx].site === site) {
-                                       $scope.ecdapp.grfTenants = $rootScope.site_tenant_map[indx].tenant;
-                                       break;
-                               }
-                       }
-                       }
-               }
-
-               $scope.ecdapp.selectGrfApp = function(t) {
-                       if(t != "Select Tenant for Grafana") {
-                       for (var indx = 0; indx < $rootScope.tenant_cluster_map.length; indx++) {
-                               if ($rootScope.tenant_cluster_map[indx].tenant === t) {
-                                       $scope.ecdapp.grf.url = $rootScope.tenant_cluster_map[indx].grf;
-                                       break;
-                               }
-                       }
-                       }
-               }
-               
-               $scope.ecdapp.selectPromTenant = function(site) {
-                       if(site != "Select Site") {
-                       for (var indx = 0; indx < $rootScope.site_tenant_map.length; indx++) {
-                               if ($rootScope.site_tenant_map[indx].site === site) {
-                                       $scope.ecdapp.promTenants = $rootScope.site_tenant_map[indx].tenant;
-                                       break;
-                               }
-                       }
-                       }
-               }
-               
-               $scope.ecdapp.selectPromApp = function(t) {
-                       if(t != "Select Tenant for Prometheus") {
-                       for (var indx = 0; indx < $rootScope.tenant_cluster_map.length; indx++) {
-                               if ($rootScope.tenant_cluster_map[indx].tenant === t) {
-                                       $scope.ecdapp.prom.url = $rootScope.tenant_cluster_map[indx].prom;
-                                       break;
-                               }
-                       }
-                       }
-               }
-
-                doIframePolling = $interval(function () {
-                           if(document.querySelector("iframe") && 
-                                       document.querySelector("iframe").contentDocument.head && 
-                                       document.querySelector("iframe").contentDocument.head.innerHTML != '')
-                           {
-                               $interval.cancel(doIframePolling);
-                               doIframePolling = undefined;
-                               $timeout.cancel(stopPolling);
-                               stopPolling = undefined;
-                               $scope.ecdapp.isCfyLoadDone = true;
-                           }
-                       },400);
-
-                       stopPolling = $timeout(function () {
-                               //$interval.cancel(doIframePolling);
-                               //doIframePolling = undefined;
-                               $timeout.cancel(stopPolling);
-                               stopPolling = undefined;
-                               $scope.ecdapp.isCfyLoadDone = true;     
-                       },30000);
-               }
-       }
-       
-       */
-
-
-});
\ No newline at end of file
diff --git a/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs_view.html b/ccsdk-app-overlay/src/main/webapp/app/ccsdk/ops/tabs_view.html
deleted file mode 100644 (file)
index aa5b1f8..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-<div id="page-content" ng-controller="tabsController">
-    <div ng-show="ecdapp.isInit">
-    <b2b-tabset tab-id-selected="activeTabsId">
-        <b2b-tab ng-repeat="tab in ecdapp.gTabs" tab-item="tab" 
-                 id="{{tab.uniqueId}}" aria-controls="{{tab.tabPanelId}}"
-                 ng-disabled="tab.disabled">
-            {{tab.title}}
-        </b2b-tab>
-    </b2b-tabset>
-    </div>
-    
-    <div class="tab-content">
-        <div id="threetab1x" role="tabpanel" aria-labelledby="uniqueTab1x" aria-hidden="{{'cfy'===activeTabsId}}" class="tab-pane" ng-class="{'active': 'cfy'===activeTabsId}">
-               <div class="row-nowrap" style="margin-top:-20px; margin-bottom: 5px;">
-               <div class="span3 form-row">
-               <label for="cfy-site-url">Site</label>
-                       <select id="cfy-site-url" name="cfy-site-url" b2b-dropdown placeholder-text="Select Site" data-ng-model="ecdapp.cfySite" ng-change="ecdapp.cfyCnslFrameReload(ecdapp.cfySite, 'cfy')" required>
-                               <option b2b-dropdown-list option-repeat="d in site_cfy_cnsl_map" value="{{d.site}}">{{d.site}}</option>
-                       </select>
-                       </div>
-                       </div>
-                       <div ng-hide="ecdapp.isFrameLoaded" class="span">
-                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                               Please wait while the content loads.
-                       </div>  
-                <iframe id="cfy_frame" ng-show="ecdapp.isFrameLoaded" aria-expanded="true" scrolling="yes" frameborder="0" style="width:100%; height: 800px;" ng-src="{{ecdapp.cfy.url}}">
-                       </iframe>
-        </div>
-        <div id="threetab2x" role="tabpanel" aria-labelledby="uniqueTab2x" aria-hidden="{{'grf'===activeTabsId}}" class="tab-pane" ng-class="{'active': 'grf'===activeTabsId}">
-               <div class="row-nowrap" style="margin-top:-20px; margin-bottom: 5px;">
-               <div class="span3 form-row">
-               <label for="grf-site-url">Site</label>
-                       <select id="grf-site-url" name="grf-site-url" b2b-dropdown placeholder-text="Select Site" data-ng-model="ecdapp.grf.site" ng-change="ecdapp.selectAppTenant(ecdapp.grf.site)" required>
-                               <option b2b-dropdown-list option-repeat="d in site_cfy_cnsl_map" value="{{d.site}}">{{d.site}}</option>
-                       </select>
-                       </div>
-                       <div class="span4 form-row">
-                       <label for="grf-ten-url">Tenant</label>
-                       <select id="grf-ten-url" name="grf-ten-url" b2b-dropdown placeholder-text="Select Tenant" data-ng-model="ecdapp.grf.tenant" ng-change="ecdapp.selectCluster(ecdapp.grf.tenant)" required>
-                               <option b2b-dropdown-list option-repeat="t in ecdapp.appTenants" value="{{t}}">{{t}}</option>
-                       </select>
-                       </div>                  
-                       <div class="span3 form-row">
-                       <label for="grf-cluster-url">Cluster</label>
-                       <select id="grf-cluster-url" name="grf-cluster-url" b2b-dropdown placeholder-text="Select K8s cluster" data-ng-model="ecdapp.grf.cluster" ng-change="ecdapp.appFrameReload(ecdapp.grf.cluster, 'grf')" required>
-                               <option b2b-dropdown-list option-repeat="c in ecdapp.appCluster" value="{{c}}">{{c}}</option>
-                       </select>
-                       </div>
-                       </div>
-                       <div ng-hide="ecdapp.isFrameLoaded" class="span">
-                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                               Please wait while the content loads.
-                       </div>
-              <iframe ng-show="ecdapp.isFrameLoaded" scrolling="yes" frameborder="0" style="width:100%; height: 800px;" ng-src="{{ecdapp.grf.url}}">
-                 </iframe>
-        </div>
-        <div id="threetab3x" role="tabpanel" aria-labelledby="uniqueTab3x" aria-hidden="{{'cnsl'===activeTabsId}}" class="tab-pane" ng-class="{'active': 'cnsl'===activeTabsId}">
-               <div class="row-nowrap" style="margin-top:-20px; margin-bottom: 5px;">
-               <div class="span3 form-row">
-               <label for="cnsl-site-url">Site</label>
-                       <select id="cnsl-site-url" name="cnsl-site-url" b2b-dropdown placeholder-text="Select Site" data-ng-model="ecdapp.cnslSite" ng-change="ecdapp.cfyCnslFrameReload(ecdapp.cnslSite, 'cnsl')" required>
-                               <option b2b-dropdown-list option-repeat="d in site_cfy_cnsl_map" value="{{d.site}}">{{d.site}}</option>
-                       </select>
-                       </div>
-                       </div>
-                       <div ng-hide="ecdapp.isFrameLoaded" class="span">
-                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                               Please wait while the content loads.
-                       </div>
-                <iframe ng-show="ecdapp.isFrameLoaded" scrolling="yes" frameborder="0" style="width:100%; height: 800px;" ng-src="{{ecdapp.cnsl.url}}">
-                       </iframe>
-        </div>
-        <div id="threetab4x" role="tabpanel" aria-labelledby="uniqueTab4x" aria-hidden="{{'k8s'===activeTabsId}}" class="tab-pane" ng-class="{'active': 'k8s'===activeTabsId}">
-               <div class="row-nowrap" style="margin-top:-20px; margin-bottom: 5px;">
-               <div class="span3 form-row">
-               <label for="k8s-site-url">Site</label>
-                       <select id="k8s-site-url" name="k8s-site-url" b2b-dropdown placeholder-text="Select Site" data-ng-model="ecdapp.k8.site" ng-change="ecdapp.selectAppTenant(ecdapp.k8.site)" required>
-                               <option b2b-dropdown-list option-repeat="d in site_cfy_cnsl_map" value="{{d.site}}">{{d.site}}</option>
-                       </select>
-                       </div>
-                       <div class="span6 form-row">
-                       <label for="k8s-ten-url">Tenant</label>
-                       <select id="k8s-ten-url" name="k8s-ten-url" b2b-dropdown placeholder-text="Select Tenant" data-ng-model="ecdapp.k8.tenant" ng-change="ecdapp.selectCluster(ecdapp.k8.tenant)" required>
-                               <option b2b-dropdown-list option-repeat="t in ecdapp.appTenants" value="{{t}}">{{t}}</option>
-                       </select>
-                       </div>
-                       <div class="span3 form-row">
-                       <label for="k8s-cluster-url">Cluster</label>
-                       <select id="k8s-cluster-url" name="k8s-cluster-url" b2b-dropdown placeholder-text="Select K8s cluster" data-ng-model="ecdapp.k8.cluster" ng-change="ecdapp.appFrameReload(ecdapp.k8.cluster, 'k8')" required>
-                               <option b2b-dropdown-list option-repeat="c in ecdapp.appCluster" value="{{c}}">{{c}}</option>
-                       </select>
-                       </div>
-                       </div>
-                       <div ng-hide="ecdapp.isFrameLoaded" class="span">
-                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                               Please wait while the content loads.
-                       </div>
-                 <iframe ng-show="ecdapp.isFrameLoaded" scrolling="yes" frameborder="0" style="width:100%; height: 800px;" ng-src="{{ecdapp.k8.url}}">
-                       </iframe>
-        </div>
-        <div id="threetab5x" role="tabpanel" aria-labelledby="uniqueTab5x" aria-hidden="{{'prom'===activeTabsId}}" class="tab-pane" ng-class="{'active': 'prom'===activeTabsId}">
-               <div class="row-nowrap" style="margin-top:-20px; margin-bottom: 5px;">
-               <div class="span3 form-row">
-               <label for="prom-site-url">Site</label>
-                       <select id="prom-site-url" name="prom-site-url" b2b-dropdown placeholder-text="Select Site" data-ng-model="ecdapp.prom.site" ng-change="ecdapp.selectAppTenant(ecdapp.prom.site)" required>
-                               <option b2b-dropdown-list option-repeat="d in site_cfy_cnsl_map" value="{{d.site}}">{{d.site}}</option>
-                       </select>
-                       </div>
-                       <div class="span6 form-row">
-                       <label for="prom-ten-url">Tenant</label>
-                       <select id="prom-ten-url" name="prom-ten-url" b2b-dropdown placeholder-text="Select Tenant" data-ng-model="ecdapp.prom.tenant" ng-change="ecdapp.selectCluster(ecdapp.prom.tenant)" required>
-                               <option b2b-dropdown-list option-repeat="t in ecdapp.appTenants" value="{{t}}">{{t}}</option>
-                       </select>
-                       </div>
-                       <div class="span3 form-row">
-                       <label for="prom-cluster-url">Cluster</label>
-                       <select id="prom-cluster-url" name="prom-cluster-url" b2b-dropdown placeholder-text="Select K8s cluster" data-ng-model="ecdapp.prom.cluster" ng-change="ecdapp.appFrameReload(ecdapp.prom.cluster, 'prom')" required>
-                               <option b2b-dropdown-list option-repeat="c in ecdapp.appCluster" value="{{c}}">{{c}}</option>
-                       </select>
-                       </div>
-                       </div>
-                       <div ng-hide="ecdapp.isFrameLoaded" class="span">
-                       <i class="icon-spinner small" role="img" aria-label="Please wait while the content loads"></i>
-                               Please wait while the content loads.
-                       </div>
-            <iframe ng-show="ecdapp.isFrameLoaded" scrolling="yes" frameborder="0" style="width:100%; height: 800px;" ng-src="{{ecdapp.prom.url}}">
-               </iframe>
-        </div>
-    </div>
-
-</div>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 79f72a8..4c779e8 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <!-- Add oparent parent -->
-
     <parent>
         <groupId>org.onap.oparent</groupId>
         <artifactId>oparent</artifactId>
@@ -14,7 +14,7 @@
     <!-- Maven parent project for convenience of building and cleaning -->
     <groupId>org.onap.ccsdk.dashboard</groupId>
     <artifactId>ccsdk-app-parent</artifactId>
-    <version>1.3.2-SNAPSHOT</version>
+    <version>1.4.0-SNAPSHOT</version>
     <packaging>pom</packaging>
     <name>ccsdk-dashboard</name>
     
             <url>${onap.nexus.url}/content/repositories/snapshots</url>
         </snapshotRepository>
     </distributionManagement>
+    <build>
+           <plugins>
+                   <plugin>
+                   <groupId>org.codehaus.mojo</groupId>
+                   <artifactId>versions-maven-plugin</artifactId>
+                   <version>2.5</version>
+                   <configuration>
+                       <generateBackupPoms>false</generateBackupPoms>
+                   </configuration>
+                       </plugin>
+               </plugins>
+    </build>
 
 </project>
index 0969948..668657e 100644 (file)
@@ -3,8 +3,8 @@
 # because they are used in Jenkins, whose plug-in doesn't support
 
 major=1
-minor=3
-patch=2
+minor=4
+patch=0
 
 base_version=${major}.${minor}.${patch}