Skip to content

Commit

Permalink
Add possibility to assign deployment techs and participants in EDMM m…
Browse files Browse the repository at this point in the history
…ode (winery#569)
  • Loading branch information
miwurster authored Mar 23, 2021
1 parent 3c67f86 commit fd796ef
Show file tree
Hide file tree
Showing 25 changed files with 430 additions and 65 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,19 @@ name: Winery CI
on: [ push, pull_request ]

jobs:

pre_job:
continue-on-error: true
runs-on: ubuntu-latest
outputs:
should_skip: ${{ steps.skip_check.outputs.should_skip }}
steps:
- id: skip_check
uses: fkirc/skip-duplicate-actions@master

java8:
needs: pre_job
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand All @@ -16,6 +27,8 @@ jobs:
run: mvn -Pjava -B package

java12:
needs: pre_job
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand All @@ -33,6 +46,8 @@ jobs:
coverage-reports: org.eclipse.winery.reporting/target/site/jacoco-aggregate/jacoco.xml

frontend:
needs: pre_job
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand Down
4 changes: 3 additions & 1 deletion .idea/runConfigurations/Winery_Server.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand All @@ -39,6 +41,7 @@
import org.eclipse.winery.model.tosca.TRelationshipType;
import org.eclipse.winery.model.tosca.TRelationshipTypeImplementation;
import org.eclipse.winery.model.tosca.TServiceTemplate;
import org.eclipse.winery.model.tosca.extensions.OTParticipant;
import org.eclipse.winery.model.tosca.utils.ModelUtilities;

import io.github.edmm.core.parser.Entity;
Expand All @@ -49,6 +52,8 @@
import io.github.edmm.core.parser.SequenceEntity;
import io.github.edmm.core.parser.support.DefaultKeys;

import static org.eclipse.winery.model.tosca.constants.Namespaces.TOSCA_WINERY_EXTENSIONS_NAMESPACE;

public class EdmmConverter {

private final Map<QName, TNodeType> nodeTypes;
Expand Down Expand Up @@ -85,20 +90,82 @@ public EdmmConverter(Map<QName, TNodeType> nodeTypes, Map<QName, TRelationshipTy
}

public EntityGraph transform(TServiceTemplate serviceTemplate) {

EntityGraph entityGraph = new EntityGraph();

setMetadata(entityGraph);

List<TNodeTemplate> nodeTemplates = serviceTemplate.getTopologyTemplate().getNodeTemplates();
List<TRelationshipTemplate> relationshipTemplates = serviceTemplate.getTopologyTemplate().getRelationshipTemplates();
if (!nodeTemplates.isEmpty()) {
entityGraph.addEntity(new MappingEntity(EntityGraph.COMPONENTS, entityGraph));
}

nodeTemplates.forEach(nodeTemplate -> createNode(nodeTemplate, entityGraph));
relationshipTemplates.forEach(relationship -> createRelation(relationship, entityGraph));

List<OTParticipant> participants = serviceTemplate.getTopologyTemplate().getParticipants();
if (participants != null && !participants.isEmpty()) {
entityGraph.addEntity(new MappingEntity(EntityGraph.PARTICIPANTS, entityGraph));
participants.forEach(participant -> createParticipant(participant, nodeTemplates, entityGraph));
}

createTechnologyMapping(nodeTemplates, entityGraph);

return entityGraph;
}

private void setMetadata(EntityGraph entityGraph) {
entityGraph.addEntity(new ScalarEntity("edm_1_0", EntityGraph.VERSION, entityGraph));
entityGraph.addEntity(new ScalarEntity("12345", EntityGraph.MULTI_ID, entityGraph));
}

private void createTechnologyMapping(List<TNodeTemplate> nodeTemplates, EntityGraph entityGraph) {

Map<String, List<TNodeTemplate>> deploymentTechnologyMapping = new HashMap<>();
for (TNodeTemplate nodeTemplate : nodeTemplates) {
Map<QName, String> attributes = nodeTemplate.getOtherAttributes();
String key = attributes.get(new QName(TOSCA_WINERY_EXTENSIONS_NAMESPACE, "deployment-technology"));
if (key != null) {
deploymentTechnologyMapping.computeIfAbsent(key, k -> new ArrayList<>());
deploymentTechnologyMapping.get(key).add(nodeTemplate);
}
}

if (!deploymentTechnologyMapping.isEmpty()) {
entityGraph.addEntity(new MappingEntity(EntityGraph.ORCHESTRATION_TECHNOLOGY, entityGraph));

deploymentTechnologyMapping.forEach((key, nodes) -> {
EntityId entity = EntityGraph.ORCHESTRATION_TECHNOLOGY.extend(key);
entityGraph.addEntity(new SequenceEntity(entity, entityGraph));
for (TNodeTemplate nodeTemplate : nodes) {
EntityId valueEntity = entity.extend(nodeTemplate.getId());
entityGraph.addEntity(new ScalarEntity(nodeTemplate.getId(), valueEntity, entityGraph));
}
});
}
}

private void createParticipant(OTParticipant participant, List<TNodeTemplate> nodeTemplates, EntityGraph entityGraph) {

EntityId participantEntity = EntityGraph.PARTICIPANTS.extend(participant.getName());
entityGraph.addEntity(new MappingEntity(participantEntity, entityGraph));

EntityId endpointEntityId = participantEntity.extend(DefaultKeys.ENDPOINT);
entityGraph.addEntity(new ScalarEntity(participant.getUrl(), endpointEntityId, entityGraph));

EntityId componentsEntityId = participantEntity.extend(DefaultKeys.COMPONENTS);
entityGraph.addEntity(new SequenceEntity(componentsEntityId, entityGraph));

for (TNodeTemplate nodeTemplate : nodeTemplates) {
Map<QName, String> attributes = nodeTemplate.getOtherAttributes();
String name = attributes.get(new QName(TOSCA_WINERY_EXTENSIONS_NAMESPACE, "participant"));
if (participant.getName().equals(name)) {
EntityId valueEntity = componentsEntityId.extend(nodeTemplate.getId());
entityGraph.addEntity(new ScalarEntity(nodeTemplate.getId(), valueEntity, entityGraph));
}
}
}

private void createRelation(TRelationshipTemplate relationship, EntityGraph entityGraph) {
EntityId sourceComponentEntityId = EntityGraph.COMPONENTS.extend(relationship.getSourceElement().getRef().getId());
// the entity will always be in the graph since we first transform the NodeTemplates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ void transformOneNodeTemplate() {
EntityGraph transform = edmmConverter.transform(serviceTemplate);

assertNotNull(transform);
assertEquals(11, transform.vertexSet().size());
assertEquals(13, transform.vertexSet().size());
}

@Test
Expand All @@ -72,7 +72,6 @@ void transformDerivedFrom() {
EntityGraph transform = edmmConverter.transform(serviceTemplate);

assertNotNull(transform);
assertEquals(11, transform.vertexSet().size());
assertTrue(transform.vertexSet().stream().anyMatch(entity ->
entity instanceof ScalarEntity
&& entity.getName().equals("extends")
Expand All @@ -94,7 +93,6 @@ void transformProperties() {
EntityGraph transform = edmmConverter.transform(serviceTemplate);

assertNotNull(transform);
assertEquals(21, transform.vertexSet().size());
assertTrue(transform.vertexSet().stream().anyMatch(entity ->
entity instanceof MappingEntity
&& entity.getName().equals("properties")
Expand Down Expand Up @@ -139,7 +137,6 @@ void transformTopologyWithRelationsAndRelationTypes() {
EntityGraph transform = edmmConverter.transform(serviceTemplate);

assertNotNull(transform);
assertEquals(47, transform.vertexSet().size());
assertTrue(transform.vertexSet().stream().anyMatch(entity ->
entity instanceof ScalarEntity
&& entity.getName().equals("hosted_on")
Expand Down Expand Up @@ -171,7 +168,6 @@ void transformTopologyWithOperations() {
EntityGraph transform = edmmConverter.transform(serviceTemplate);

assertNotNull(transform);
assertEquals(14, transform.vertexSet().size());

Optional<Entity> operations = transform.getEntity(Arrays.asList("0", "components", "test_node_4", "operations"));
assertTrue(operations.isPresent());
Expand Down Expand Up @@ -247,6 +243,7 @@ void transformTopology() {
" extends: depends_on\n" +
" connects_to:\n" +
" extends: depends_on\n" +
"multi_id: '12345'\n" +
"component_types:\n" +
" https_ex.orgtoscatoedmm__test_node_type_2:\n" +
" extends: software_component\n" +
Expand All @@ -266,6 +263,7 @@ void transformTopology() {
" https_ex.orgtoscatoedmm__test_node_type_4:\n" +
" extends: web_application\n" +
" software_component:\n" +
" extends: base\n", stringWriter.toString());
" extends: base\n" +
"version: edm_1_0\n", stringWriter.toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/********************************************************************************
* Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
********************************************************************************/
table {
width: 210px;
table-layout: fixed;
border: 1px solid #ddd;
}

th {
background-color: #cfd8dc;
color: #000;
text-align: left;
}

th,
td {
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #ddd;
padding-left: 2px;
}

tr {
cursor: pointer;
}

tr:nth-child(even) {
background-color: #f2f2f2;
}

.table-td div {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
position: relative;
width: auto;
max-width: 100%;
-webkit-transition: max-width linear 1ms;
transition: max-width linear 1ms;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!--
* Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
-->

<div *ngIf="isEmpty()" style="color: dimgray; text-align: center">
<span>No deployment technologies available.</span>
</div>

<table>
<thead>
<tr>
<th>Name</th>
<th style="width: 60px">Use</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let p of deploymentTechnologies">
<td class="table-td"
[class.cell-with-comment]="isEllipsisActive(name)">
<div #name>{{ p.name }}</div>
<span class="cell-comment">{{ p.name }}</span>
</td>
<td class="table-td">
<div style="margin-left: 2px; margin-top: 4px;">
<input type="radio" id="{{ node.id }}--{{ p.id }}"
[name]="node.id"
[value]="p.id"
(change)="toggleMembership(p)"
[checked]="isMember(p)">
<label for="{{ node.id }}--{{ p.id }}"></label>
</div>
</td>
</tr>
</tbody>
</table>
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/********************************************************************************
* Copyright (c) 2021 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache Software License 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
********************************************************************************/

import { Component, Input, OnInit } from '@angular/core';
import { NgRedux } from '@angular-redux/store';
import { TNodeTemplate } from '../models/ttopology-template';
import { IWineryState } from '../redux/store/winery.store';
import { WineryActions } from '../redux/actions/winery.actions';
import { BackendService } from '../services/backend.service';
import { DeploymentTechnology } from '../models/deployment-technology';
import { QName } from '../../../../shared/src/app/model/qName';
import { TOSCA_WINERY_EXTENSIONS_NAMESPACE } from '../models/namespaces';

@Component({
selector: 'winery-assign-deployment-technology',
templateUrl: './assign-deployment-technology.component.html',
styleUrls: ['./assign-deployment-technology.component.css']
})
export class AssignDeploymentTechnologyComponent implements OnInit {

static QNAME_DEPLOYMENT_TECHNOLOGY = QName.create(TOSCA_WINERY_EXTENSIONS_NAMESPACE, 'deployment-technology').qName;

@Input() readonly: boolean;
@Input() deploymentTechnologies: DeploymentTechnology[];
@Input() node: TNodeTemplate;

constructor(private ngRedux: NgRedux<IWineryState>,
private ngActions: WineryActions,
private backendService: BackendService) {
}

ngOnInit() {
this.backendService.requestSupportedDeploymentTechnologies().subscribe(value => this.deploymentTechnologies = value);
}

isEllipsisActive(cell): boolean {
return (cell.offsetWidth < cell.scrollWidth);
}

isMember(dt: DeploymentTechnology) {
const value = this.node.otherAttributes[AssignDeploymentTechnologyComponent.QNAME_DEPLOYMENT_TECHNOLOGY];
return value && dt.id === value;
}

toggleMembership(dt: DeploymentTechnology) {
this.ngRedux.dispatch(this.ngActions.assignDeploymentTechnology(this.node, dt.id));
}

isEmpty(): boolean {
return !this.deploymentTechnologies || this.deploymentTechnologies.length === 0;
}
}
Loading

0 comments on commit fd796ef

Please sign in to comment.