updateNode: function(nodeGroup, node, nodeTemplate, nodeType, oX, oY, topology) { // update text nodeGroup.select('.simple-title').text(commonNodeRendererService.getDisplayId(node, true)); // update version nodeGroup.select('.simple-version').text(function() { if (nodeTemplate.properties) { if (typeof nodeTemplate.properties.version === 'string') { return 'v' + nodeTemplate.properties.version; } } }); // runtime infos if (this.isRuntime) { var runtimeGroup = nodeGroup.select('#runtime'); var nodeInstances = null; var nodeInstancesCount = null; if (_.defined(topology.instances)) { nodeInstances = topology.instances[node.id]; if (_.defined(nodeInstances)) { nodeInstancesCount = Object.keys(nodeInstances).length; } } // TODO better draw network node if (!toscaService.isOneOfType(['tosca.nodes.Network'], nodeTemplate.type, topology.nodeTypes)) { this.drawRuntimeInfos(runtimeGroup, nodeInstances, nodeInstancesCount, oX, oY); } } },
doGetTargets: function(sourceElementName, requirement, nodeTemplates, nodeTypes, capabilityTypes, relationshipType, preferedTargetName) { var matches = []; var preferedMatch = null; // valid targets is an array of array, first level elements are all required (AND) while only one of the elements of inner array is required. var validTargets = [[requirement.type]]; if(_.defined(relationshipType) && _.defined(relationshipType.validTargets) && relationshipType.validTargets.length > 0) { validTargets.push(relationshipType.validTargets); } for (var templateName in nodeTemplates) { if (templateName !== sourceElementName && nodeTemplates.hasOwnProperty(templateName)) { var candidate = nodeTemplates[templateName]; // try to match on node type first (if match this means that there is no capacity constraint, we won't be able to match cardinalities on theses relationships). // but that's allowed by TOSCA Simple profile. var match = this.getNodeTarget(validTargets, candidate, nodeTypes); if(match === null) { match = this.getCapabilityTarget(validTargets, candidate, nodeTypes, capabilityTypes); } if(match !== null) { matches.push(match); } if(templateName === preferedTargetName) { preferedMatch = match; } } } return { targets: matches, relationshipType: relationshipType, preferedMatch: preferedMatch }; },
recursiveTreeSort: function (node) { var children = []; for(var i = 0; i < node.children.length; i++) { var child = node.children[i]; if(child.children.length >0) { this.recursiveTreeSort(child); } var candidatePosition = -1; if(_.defined(child.before)) { // ensure the node is added before. for(var j=0; j<children.length && candidatePosition === -1; j++) { if(child.before.indexOf(children[j]) >= 0) { candidatePosition = j; } } } if(_.defined(child.after)) { // ensure the node is added after. for(var k=children.length-1; k>candidatePosition; k--) { if(child.after.indexOf(children[k]) >= 0) { candidatePosition = k+1; } } } if(candidatePosition === -1) { children.push(child); } else { children.splice(candidatePosition, 0, child); } } node.children = children; },
var extractErrorMessage = function (rejection) { if (_.defined(rejection.data)) { if (_.defined(rejection.data.error)) { var error = rejection.data.error; // Redirect to homepage when the user is not authenticated if (error.code === 100) { $window.location.href = '/'; } else { return { status: rejection.status, data: _.defined(error.code) ? 'ERRORS.' + error.code : 'ERRORS.UNKNOWN', code: error.code }; } } else { // Error not defined ==> return the data part return { status: rejection.status, data: rejection.data }; } } else { // rejection.data not defined ==> unknown error return { status: rejection.status, data: 'ERRORS.UNKNOWN' }; } };
$scope.getPropertyValue = function(metaPropId) { if (_.defined($scope.application) && _.defined($scope.application.metaProperties)) { return $scope.application.metaProperties[metaPropId]; } else if (_.defined($scope.cloud) && _.defined($scope.cloud.metaProperties)) { return $scope.cloud.metaProperties[metaPropId]; } };
$scope.propertySave = function(data, unit) { delete $scope.unitError; if (_.isBoolean(data)) { data = data.toString(); } else if (_.isEmpty(data)) { data = null; } if (!_.isEmpty(data) && _.defined($scope.definitionObject.units)) { if (_.undefined(unit)) { unit = $scope.definitionObject.uiUnit; } data += ' ' + unit; } // check constraint here var propertyRequest = { propertyName: $scope.propertyName, propertyDefinition: $scope.definition, propertyValue: data }; if (_.defined($scope.definition.suggestionId) && _.defined(data) && data !== null) { return propertySuggestionServices.get({ input: data, limit: 5, suggestionId: $scope.definition.suggestionId }).$promise.then(function(suggestionResult) { var promise; $scope.propertySuggestionData = { suggestions: suggestionResult.data, propertyValue: data }; if (suggestionResult.data.indexOf(data) < 0) { var modalInstance = $modal.open({ templateUrl: 'propertySuggestionModal.html', controller: PropertySuggestionModalCtrl, scope: $scope }); promise = modalInstance.result.then(function(modalResult) { if (suggestionResult.data.indexOf(modalResult) < 0) { propertySuggestionServices.add([], { suggestionId: $scope.definition.suggestionId, value: modalResult }, null); } propertyRequest.propertyValue = modalResult; return callSaveService(propertyRequest); }, function() { return $translate("CANCELLED"); }); } else { promise = callSaveService(propertyRequest); } return promise; }); } else { return callSaveService(propertyRequest); } };
function enrichPAASEvent(event) { event.type = $scope.eventTypeLabels[event.rawType]; switch (event.rawType) { case 'paasdeploymentstatusmonitorevent': event.message = { template: 'APPLICATIONS.RUNTIME.EVENTS.DEPLOYMENT_STATUS_MESSAGE', data: { status: 'APPLICATIONS.' + event.deploymentStatus } }; break; case 'paasinstancestatemonitorevent': if (_.defined(event.instanceState)) { event.message = { template: 'APPLICATIONS.RUNTIME.EVENTS.INSTANCE_STATE_MESSAGE', data: { state: event.instanceState, nodeId: event.nodeTemplateId, instanceId: event.instanceId } }; } else { event.message = { template: 'APPLICATIONS.RUNTIME.EVENTS.INSTANCE_DELETED_MESSAGE', data: { nodeId: event.nodeTemplateId, instanceId: event.instanceId } }; } break; case 'paasinstancestoragemonitorevent': if (_.defined(event.instanceState)) { event.message = { template: 'APPLICATIONS.RUNTIME.EVENTS.STORAGE_MESSAGE', data: { state: event.instanceState, nodeId: event.nodeTemplateId, instanceId: event.instanceId, volumeId: event.volumeId } }; } else { event.message = { template: 'APPLICATIONS.RUNTIME.EVENTS.INSTANCE_DELETED_MESSAGE', data: { nodeId: event.nodeTemplateId, instanceId: event.instanceId } }; } break; case 'paasmessagemonitorevent': event.message = { template: event.message }; break; } }
autoOpenRelationshipModal: function(sourceNodeTemplateName, targetNodeTemplateName) { var scope = this.scope; var sourceNodeTemplate = scope.topology.topology.nodeTemplates[sourceNodeTemplateName]; var targetNodeTemplate = scope.topology.topology.nodeTemplates[targetNodeTemplateName]; if (_.defined(sourceNodeTemplate) && _.defined(targetNodeTemplate)) { // let's try to find the requirement / for now we just support hosted on but we should improve that... var requirementName = nodeTemplateService.getContainerRequirement(sourceNodeTemplate, scope.topology.nodeTypes, scope.topology.relationshipTypes, scope.topology.capabilityTypes); this.openSearchRelationshipModal(sourceNodeTemplateName, requirementName, targetNodeTemplateName); } },
function refreshSelectedNodeInstancesCount() { if (_.defined($scope.selectedNodeTemplate)) { if (_.defined($scope.topology.instances) && _.defined($scope.topology.instances[$scope.selectedNodeTemplate.name])) { $scope.selectedNodeTemplate.instancesCount = Object.keys($scope.topology.instances[$scope.selectedNodeTemplate.name]).length; } else { $scope.selectedNodeTemplate.instancesCount = 0; } if (_.undefined($scope.selectedNodeTemplate.newInstancesCount)) { $scope.selectedNodeTemplate.newInstancesCount = $scope.selectedNodeTemplate.instancesCount; } } }
$scope.updateProperty = function(type, propertyDefinitionId, value) { var updateApplicationPropertyObject = { 'definitionId': propertyDefinitionId, 'value': value }; // In future, we need to add component here if (_.defined($scope.application)) { return updateApplicationMetaProperty(updateApplicationPropertyObject); } else if (_.defined($scope.cloud)) { return updateCloudMetaProperty(updateApplicationPropertyObject); } };
expand: function(expandedNodes, fullPath, node, isExpandable) { if(isExpandable) { if(fullPath !== node.fullPath && fullPath.indexOf(node.fullPath) > -1) { expandedNodes.push(node); } } if(_.defined(node) && _.defined(node.children)) { for(var i=0;i<node.children.length;i++) { this.expand(node.children[i], true); } } },
$scope.saveUnit = function(unit) { $scope.definitionObject.uiUnit = unit; if (_.defined($scope.definitionObject.uiValue)) { var savePromise = $scope.propertySave($scope.definitionObject.uiValue, unit); if (_.defined(savePromise)) { savePromise.then(function(error) { if (_.defined(error)) { $scope.unitError = error; } }); } } };
}, function(result) { $scope.topologyDTO = result.data; topologyJsonProcessor.process($scope.topologyDTO); // initialize compute and network icons from the actual tosca types (to match topology representation). if (_.defined($scope.topologyDTO.nodeTypes['tosca.nodes.Compute']) && _.isNotEmpty($scope.topologyDTO.nodeTypes['tosca.nodes.Compute'].tags)) { $scope.computeImage = toscaService.getIcon($scope.topologyDTO.nodeTypes['tosca.nodes.Compute'].tags); } if (_.defined($scope.topologyDTO.nodeTypes['tosca.nodes.Network']) && _.isNotEmpty($scope.topologyDTO.nodeTypes['tosca.nodes.Network'].tags)) { $scope.networkImage = toscaService.getIcon($scope.topologyDTO.nodeTypes['tosca.nodes.Network'].tags); } if (_.defined($scope.topologyDTO.nodeTypes['tosca.nodes.BlockStorage']) && _.isNotEmpty($scope.topologyDTO.nodeTypes['tosca.nodes.BlockStorage'].tags)) { $scope.storageImage = toscaService.getIcon($scope.topologyDTO.nodeTypes['tosca.nodes.BlockStorage'].tags); } // process topology data $scope.inputs = result.data.topology.inputs; $scope.outputProperties = result.data.topology.outputProperties; $scope.outputCapabilityProperties = result.data.topology.outputCapabilityProperties; $scope.outputAttributes = result.data.topology.outputAttributes; $scope.inputArtifacts = result.data.topology.inputArtifacts; $scope.nodeTemplates = $scope.topologyDTO.topology.nodeTemplates; $scope.nodeTypes = $scope.topologyDTO.nodeTypes; $scope.outputNodes = []; $scope.inputsSize = 0; $scope.outputPropertiesSize = 0; $scope.outputAttributesSize = 0; $scope.inputArtifactsSize = 0; if (angular.isDefined(result.data.topology.inputs)) { $scope.inputsSize = Object.keys(result.data.topology.inputs).length; } if (angular.isDefined($scope.outputProperties)) { $scope.outputNodes = Object.keys($scope.outputProperties); $scope.outputPropertiesSize = Object.keys($scope.outputProperties).length; refreshOutputProperties(); } if (angular.isDefined($scope.outputCapabilityProperties)) { $scope.outputNodes = _.union($scope.outputNodes, Object.keys($scope.outputCapabilityProperties)); refreshOutputProperties(); } if (angular.isDefined($scope.outputAttributes)) { $scope.outputNodes = _.union($scope.outputNodes, Object.keys($scope.outputAttributes)); $scope.outputAttributesSize = Object.keys($scope.outputAttributes).length; } if (angular.isDefined(result.data.topology.inputArtifacts)) { $scope.inputArtifactsSize = Object.keys(result.data.topology.inputArtifacts).length; } });
var search = function(from, additionalBody, useCache) { if (!from) { pagination.reset(); from = pagination.from; } var baseQuery = { query: queryProvider.query, from: from, size: maxSearchSize }; if (useParam) { // URL parameters based query var searchRequest = baseQuery; if (_.defined(params)) { searchRequest = _.merge(params, searchRequest); } resource.search(searchRequest, function(searchResult) { setCachedResult(searchRequest, undefined, searchResult); setResults(from); }); } else { // var searchBody = baseQuery; if (_.defined(body)) { searchBody = _.merge(body, searchBody); } if(_.defined(additionalBody)){ searchBody = _.merge(searchBody, additionalBody); pagination.searchContext.additionalBody = additionalBody; } if(isFiltered){ searchBody.filters=queryProvider.filters; } if(!isPaginatedAPI) { // mimic pagination from ui side. searchBody.from = 0; searchBody.size = maxSearchSize * maxPageNumbers; } if(useCache && isCachedQuery(params, searchBody)) { setResults(from); return; } resource.search(params, angular.toJson(searchBody), function(searchResult) { setCachedResult(params, searchBody, searchResult); setResults(from); }); } };
Object.keys(interfaceObj.operations).forEach(function(operation) { if (_.defined(interfaceObj.operations[operation].inputParameters)) { Object.keys(interfaceObj.operations[operation].inputParameters).forEach(function(paramName) { var inputParameter = interfaceObj.operations[operation].inputParameters[paramName]; if (inputParameter.definition) { var propteryDefinitionModel = {}; propteryDefinitionModel.type = inputParameter.type; propteryDefinitionModel.required = inputParameter.required; propteryDefinitionModel.name = paramName; propteryDefinitionModel.default = inputParameter.paramValue || ''; // needed for the directive propteryDefinitionModel.password = false; propteryDefinitionModel.constraints = null; propteryDefinitionModel.from = operation; if (inputParameter.type === 'boolean') { inputParameter.paramValue = false; } if (inputParameter.type === 'timestamp') { inputParameter.paramValue = Date.now(); } inputParameter.definitionModel = propteryDefinitionModel; } else { //we don't want function type params in the ui delete interfaceObj.operations[operation].inputParameters[paramName]; } }); } });
}, angular.toJson(newConfiguration), function success(response) { $scope.configuration = newConfiguration; if (_.defined(response.error)) { var errorsHandle = $q.defer(); return errorsHandle.resolve(response.error); } }).$promise;
$scope.initCollapse = function() { if (_.defined($scope.collapse)) { $scope.isMetaPropsCollapsed = $scope.collapse; } else { $scope.isMetaPropsCollapsed = true; } };
$scope.showSelected = function(node) { var dirName = node.fullPath.substring(node.fullPath.split('/', 2).join('/').length+1); $scope.filePath = dirName; var selectedUrl; if(_.defined(node.artifactId)) { // temp file under edition selectedUrl = '/rest/latest/editor/' + $scope.topology.topology.id + '/file/' + node.artifactId; } else { // commited file selectedUrl = '/static/tosca/' + $scope.topology.topology.archiveName + '/' + $scope.topology.topology.archiveVersion + node.fullPath; } _.isImage(selectedUrl).then(function(isImage) { if(isImage) { $scope.imageUrl = selectedUrl; $scope.isImage = isImage; $scope.$apply(); } else { $scope.isImage = false; $http({method: 'GET', transformResponse: function(d) { return d; }, url: selectedUrl}) .then(function(result) { $scope.aceFilePath = dirName; aceEditor.getSession().setValue(result.data); $scope.mode = explorerService.getMode(node); }); } }); };
drawRuntimeInfos: function(runtimeGroup, nodeInstances, nodeInstancesCount, rectOriginX, rectOriginY) { var currentY = rectOriginY + 40; var deletedCount = 0; if (_.defined(nodeInstances) && nodeInstancesCount > 0) { //the deployment status is no more unknown this.removeRuntimeCount(runtimeGroup, 'runtime-count-unknown'); var successCount = this.getNumberOfInstanceByStatus(nodeInstances, 'SUCCESS'); var failureCount = this.getNumberOfInstanceByStatus(nodeInstances, 'FAILURE'); deletedCount = this.getNumberOfInstanceByStatus(nodeInstances, null); if (nodeInstancesCount === successCount) { runtimeGroup.append('circle').attr('cx', rectOriginX + this.width - 25).attr('cy', rectOriginY + 75).attr('r', '16') .attr('orient', 'auto').attr('style', 'stroke: none; fill: green'); } else if (nodeInstancesCount === failureCount) { runtimeGroup.append('circle').attr('cx', rectOriginX + this.width - 25).attr('cy', rectOriginY + 75).attr('r', '16') .attr('orient', 'auto').attr('style', 'stroke: none; fill: red'); } else if (nodeInstancesCount === deletedCount) { runtimeGroup.append('circle').attr('cx', rectOriginX + this.width - 25).attr('cy', rectOriginY + 75).attr('r', '16').attr( 'orient', 'auto').attr('style', 'stroke: none; fill: gray'); } else { runtimeGroup.append('circle').attr('cx', rectOriginX + this.width - 25).attr('cy', rectOriginY + 75).attr('r', '16') .attr('orient', 'auto').attr('style', 'stroke: none; fill: orange'); } } else { //unknown status this.drawRuntimeCount(runtimeGroup, 'runtime-count-unknown', rectOriginX, currentY, '\uf110'); runtimeGroup.append('circle').attr('cx', rectOriginX + this.width - 25).attr('cy', rectOriginY + 75).attr('r', '16').attr( 'orient', 'auto').attr('style', 'stroke: none; fill: gray'); } // draw the instance count at good size runtimeGroup = commonNodeRendererService.appendCount(runtimeGroup, nodeInstancesCount, deletedCount, rectOriginX, rectOriginY, 30, 80, this.width); },
applicationServices.create([], angular.toJson(application), function (result) { if (_.defined(result.error)) { toaster.pop('error', $translate.instant('ERRORS.' + result.error.code), $translate.instant('ERRORS.' + result.error.code), 6000, 'trustedHtml'); } else { $scope.openApplication(result.data); } });
return function(id) { if(_.defined(id)) { var splitted = id.split(':'); return splitted[splitted.length-1]; } return id; };
$http.get('rest/latest/orchestrators/' + orchestrator.id + '/locationsupport').success(function(response) { if (_.defined(response.data)) { locationSupport = response.data; $scope.multipleLocations = locationSupport.multipleLocations; $scope.locationTypes = locationSupport.types; } });
// refresh the actual selected cloud. function refreshSelectedCloud() { delete $scope.deploymentPropertyDefinitions; delete $scope.selectedCloud; // var clouds = $scope.clouds; if (_.defined($scope.clouds)) { // select the cloud that is currently associated with the environment var found = false, i = 0; while (!found && i < $scope.clouds.length) { if ($scope.clouds[i].id === $scope.selectedEnvironment.cloudId) { $scope.selectedCloud = $scope.clouds[i]; found = true; } i++; } if (found) { refreshDeploymentPropertyDefinitions(); } else { // No cloud rights or cloud not enabled or no loud defined if ($scope.selectedEnvironment.hasOwnProperty('cloudId')) { var errorTitle = $translate('APPLICATIONS.DEPLOYMENT.CLOUD_ERROR_TITLE'); var errorMessage = $translate('APPLICATIONS.DEPLOYMENT.CLOUD_ERROR_MESSAGE'); toaster.pop('error', errorTitle, errorMessage, 0, 'trustedHtml', null); } } } }
var doSubscribe = function doSubscribe(appRuntimeInformation, stateId) { $scope.applicationEventServices.subscribeToInstanceStateChange(stateId, onInstanceStateChange); if (_.defined(appRuntimeInformation)) { for (var nodeId in appRuntimeInformation) { if (appRuntimeInformation.hasOwnProperty(nodeId)) { $scope.outputAttributesValue[nodeId] = {}; var nodeInformation = appRuntimeInformation[nodeId]; for (var instanceId in nodeInformation) { if (nodeInformation.hasOwnProperty(instanceId)) { $scope.outputAttributesValue[nodeId][instanceId] = {}; var allAttributes = nodeInformation[instanceId].attributes; for (var attribute in allAttributes) { if (allAttributes.hasOwnProperty(attribute) && isOutput(nodeId, attribute, 'outputAttributes')) { $scope.outputAttributesValue[nodeId][instanceId][attribute] = allAttributes[attribute]; } } if (Object.keys($scope.outputAttributesValue[nodeId][instanceId]).length === 0) { delete $scope.outputAttributesValue[nodeId][instanceId]; } } } var nbOfInstances = Object.keys($scope.outputAttributesValue[nodeId]).length; if (nbOfInstances === 0) { delete $scope.outputAttributesValue[nodeId]; } } } } };
var onInstanceStateChange = function(type, event) { if (_.undefined(event.instanceState)) { // Delete event if (_.defined($scope.outputAttributesValue[event.nodeTemplateId])) { delete $scope.outputAttributesValue[event.nodeTemplateId][event.instanceId]; if (Object.keys($scope.outputAttributesValue[event.nodeTemplateId]).length === 0) { delete $scope.outputAttributesValue[event.nodeTemplateId]; } } } else { // Add modify event var allAttributes = event.attributes; for (var attribute in allAttributes) { if (allAttributes.hasOwnProperty(attribute) && isOutput(event.nodeTemplateId, attribute, 'outputAttributes')) { if (_.undefined($scope.outputAttributesValue[event.nodeTemplateId])) { $scope.outputAttributesValue[event.nodeTemplateId] = {}; } if (_.undefined($scope.outputAttributesValue[event.nodeTemplateId][event.instanceId])) { $scope.outputAttributesValue[event.nodeTemplateId][event.instanceId] = {}; } // fill up OUTPUT ATTRIBUTES $scope.outputAttributesValue[event.nodeTemplateId][event.instanceId][attribute] = allAttributes[attribute]; } } } $scope.$apply(); };
var getScalingProperty = function(scalableCapability, propertyName) { var propertyEntry = scalableCapability.propertiesMap[propertyName]; var propertyValue = 1; if (_.defined(propertyEntry) && _.defined(propertyEntry.value)) { if (_.defined(propertyEntry.value.value)) { // Scalar propertyValue = parseInt(propertyEntry.value.value); } else if (_.defined(propertyEntry.value.function) && _.defined(propertyEntry.value.parameters) && propertyEntry.value.parameters.length > 0) { // Get input propertyValue = propertyEntry.value; } } return propertyValue; };
}).$promise.then(function(result) { if (_.defined(result.data)) { return result.data; } else { return []; } });
var injectPropertyDefinitionToInterfaces = function(interfaces) { if (_.defined(interfaces)) { angular.forEach(interfaces, function(interfaceObj, interfaceName) { Object.keys(interfaceObj.operations).forEach(function(operation) { if (_.defined(interfaceObj.operations[operation].inputParameters)) { Object.keys(interfaceObj.operations[operation].inputParameters).forEach(function(paramName) { var inputParameter = interfaceObj.operations[operation].inputParameters[paramName]; if (inputParameter.definition) { inputParameter.interface = interfaceName; inputParameter.operation = operation; inputParameter.paramValue = inputParameter.paramValue || ''; // if (inputParameter.type === 'timestamp') { // inputParameter.paramValue = Date.now(); // } } else { //we don't want function type params in the ui delete interfaceObj.operations[operation].inputParameters[paramName]; } }); } }); }); } };
}, angular.toJson(updateApplicationEnvironmentRequest)).$promise.then(function(response) { if (_.defined(response.error)) { toaster.pop('error', $translate('ERRORS.' + response.error.code), response.error.message, 4000, 'trustedHtml', null); } else { updateEnvironment(environmentId, fieldName, realFieldValue); } }, function(errorResponse) {
getScalingPolicy: function(node) { if (_.defined(node.capabilitiesMap) && _.defined(node.capabilitiesMap.scalable)) { var scalableCapability = node.capabilitiesMap.scalable.value; var min = getScalingProperty(scalableCapability, 'min_instances'); var max = getScalingProperty(scalableCapability, 'max_instances'); var init = getScalingProperty(scalableCapability, 'default_instances'); // If min == max == default == 1 we consider that the node is not scalable if (min !== 1 || max !== 1 || init !== 1) { return { minInstances: min, maxInstances: max, initialInstances: init }; } } },