Skip to content
This repository has been archived by the owner on Oct 17, 2018. It is now read-only.

Commit

Permalink
Now able to parse resource files and transform them into a diagram
Browse files Browse the repository at this point in the history
  • Loading branch information
quintesse committed Jul 25, 2018
1 parent 2f2b903 commit a80e788
Show file tree
Hide file tree
Showing 15 changed files with 1,415 additions and 80 deletions.
1,146 changes: 1,146 additions & 0 deletions public/app.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'semantic-ui-css/semantic.min.css';
import { Dimmer, Loader } from 'semantic-ui-react';
import './App.css';
import TMainPage from './t-design/MainPage';
import T2MainPage from './t2-design/MainPage';
import DiagramWithTemplate from './t2-design/DiagramWithTemplate';
import GMainPage from './g-design/MainPage';
import Home from './pages/Home';
import BoosterMatrix from './pages/BoosterMatrix';
Expand All @@ -31,7 +31,7 @@ class App extends Component {
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/t-design' component={TMainPage}/>
<Route path='/t2-design' component={T2MainPage}/>
<Route path='/t2-design' component={DiagramWithTemplate}/>
<Route path='/g-design' component={GMainPage}/>
<Route path='/matrix' component={BoosterMatrix}/>
</Switch>
Expand Down
34 changes: 34 additions & 0 deletions src/t2-design/DiagramWithTemplate.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.t2-design-withtemplate {
display: flex;
width: 100%;
height: 100%;
}

.t2-design-withtemplate table {
width: 100%;
height: 100%;
}

.t2-design-withtemplate td {
padding: 0px;
margin: 0px;
}

.templatecell {
width: 40%;
}

.templatecontainer {
width: 100%;
height: 100%;
}

.templatebox {
width: 100%;
height: 100%;
}

.templatebox textarea {
width: 100%;
height: 400px;
}
166 changes: 166 additions & 0 deletions src/t2-design/DiagramWithTemplate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import React from 'react';
import classNames from 'classnames';
import _ from "lodash";

import { Form } from 'semantic-ui-react'

import Topology from "./components/Topology";

import './DiagramWithTemplate.css';

class DiagramWithTemplate extends React.Component {

constructor(props) {
super(props);
this.state = {
selectedItemId: null,
templateJson: null,
layout: {
nodes: {
r1: {type: 'route', belongsTo: 's1'},
s1: {type: 'service', name: 'Placeholder'},
d1: {type: 'storage', belongsTo: 's1'},
},
edges: {
l1: {from: 'r1', to: 's1'},
l2: {from: 's1', to: 'd1'},
}
}
};
}

componentDidMount() {
fetch("/app.json")
.then(response => response.text())
.then(text => this.updateLayoutFromText(text));
}

updateLayoutFromText = (text) => {
let json = JSON.parse(text);
this.setState({templateText: text, templateJson: json, layout: this.templateToLayout(json)})
}

templateToLayout = (template) => {
let layout = { nodes: {}, edges: {} };

// First find and transform our "services"
this.itemsByKind(template, "DeploymentConfig").forEach(item => this.transformDeploymentConfig(layout, template, item));

// Find and transform Routes
this.itemsByKind(template, "Route").forEach(item => this.transformRoute(layout, template, item));

// Find and transform ConfigMaps
this.itemsByKind(template, "ConfigMap").forEach(item => this.transformConfigMap(layout, template, item));

// Find and transform PersistentVolumeClaims
this.itemsByKind(template, "PersistentVolumeClaim").forEach(item => this.transformPersistentVolumeClaim(layout, template, item));

return layout;
}

// DeploymentConfigs, BuildConfigs and Services

transformDeploymentConfig = (layout, template, item) => {
let hasBC = this.itemsByKind(template, "BuildConfig").filter(i => i.metadata.name === item.metadata.name).length > 0;
let services = this.itemsByKind(template, "Service").filter(i => this.deploymentConfigSelector(i) === item.metadata.name).map(i => i.metadata.name);
layout.nodes[this.serviceId(item)] = ({ type: 'service', name: item.metadata.name, hasBuildConfig: hasBC, services: services });
}

serviceId = (item) => this.serviceIdFromName(item.metadata.name);

serviceIdFromName = (name) => 'srv-' + name;

// Routes

transformRoute = (layout, template, item) => {
let id = this.routeId(item);
let to = this.routeBelongsTo(layout, template, item);
layout.nodes[id] = ({ type: 'route', name: item.metadata.name, belongsTo: to });
layout.edges[id+"-"+to] = ({ type: 'line', from: id, to: to });
}

routeBelongsTo = (layout, template, item) => {
let srvKind = item.spec.to.kind;
let srvName = item.spec.to.name;
let items = this.itemsByKind(template, srvKind).filter(i => i.metadata.name === srvName);
return this.serviceIdFromName(this.deploymentConfigSelector(items[0]));
}

routeId = (item) => 'r-' + item.metadata.name;

// ConfigMaps

transformConfigMap = (layout, template, item) => {
let id = this.configMapId(item);
layout.nodes[id] = ({ type: 'configmap', name: item.metadata.name });

// Try making connections
this.itemsByKind(template, "DeploymentConfig")
.filter(i => _.get(i, 'spec.template.spec.containers', [])
.filter(v => _.get(v, 'env', [])
.filter(e => _.get(e, 'valueFrom.configMapKeyRef.name') === item.metadata.name).length > 0).length > 0)
.forEach(s => {
let to = this.serviceId(s);
layout.edges[id+"-"+to] = ({ type: 'line', from: id, to: to });
});
}

configMapId = (item) => 'cm-' + item.metadata.name;

// PersistentVolumeClaims

transformPersistentVolumeClaim = (layout, template, item) => {
let id = this.persistentVolumeClaimId(item);
layout.nodes[id] = ({ type: 'storage', name: item.metadata.name });

// Try making connections
this.itemsByKind(template, "DeploymentConfig")
.filter(i => _.get(i, 'spec.template.spec.volumes', [])
.filter(v => _.get(v, 'persistentVolumeClaim.claimName') === item.metadata.name).length > 0)
.forEach(s => {
let to = this.serviceId(s);
layout.edges[id+"-"+to] = ({ type: 'line', from: id, to: to });
});
}

persistentVolumeClaimId = (item) => 'pvc-' + item.metadata.name;

deploymentConfigSelector = (item) => _.get(item, 'spec.selector.deploymentconfig', _.get(item, 'spec.selector.deploymentConfig'));

itemsByKind = (template, kind) =>
template.items.filter(i => kind.toLowerCase() === i.kind.toLowerCase());

onSelectItem = (id, item) => {
this.setState({selectedItemId: id});
}

render() {
return (
<div className={classNames("t2-design-withtemplate")}>
<table>
<tbody>
<tr>
<td className={classNames("topocell")}>
<Topology layout={this.state.layout} onSelect={this.onSelectItem}/>
</td>
<td className={classNames("templatecell")}>
<div className={classNames("templatecontainer")}>
<Form>
<Form.TextArea
className={classNames("templatebox")}
value={this.state.templateText}
onChange={(e, t) => this.setState({templateText: t.value})}
wrap="off" />
<Form.Button onClick={() => this.updateLayoutFromText(this.state.templateText)}>Apply</Form.Button>
</Form>
</div>
</td>
</tr>
</tbody>
</table>
</div>
);
}
}

export default DiagramWithTemplate;
2 changes: 0 additions & 2 deletions src/t2-design/MainPage.css

This file was deleted.

46 changes: 0 additions & 46 deletions src/t2-design/MainPage.js

This file was deleted.

2 changes: 0 additions & 2 deletions src/t2-design/components/ConfigMap.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import IconItem from "./IconItem";

Expand Down
4 changes: 0 additions & 4 deletions src/t2-design/components/DOMRef.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ import PropTypes from 'prop-types';

class DOMRef extends React.Component {

constructor(props) {
super(props);
}

componentDidMount() {
let node = ReactDOM.findDOMNode(this);
this.props.domRef(this.props, node);
Expand Down
2 changes: 0 additions & 2 deletions src/t2-design/components/IconItem.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import React from 'react';
import ReactDOM from "react-dom";
import PropTypes from 'prop-types';
import classNames from 'classnames';
import _ from "lodash";

import { Icon } from 'semantic-ui-react'

Expand Down
1 change: 0 additions & 1 deletion src/t2-design/components/Item.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import ReactDOM from "react-dom";
import PropTypes from 'prop-types';

import DOMRef from './DOMRef'
Expand Down
2 changes: 0 additions & 2 deletions src/t2-design/components/Route.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import IconItem from "./IconItem";

Expand Down
20 changes: 17 additions & 3 deletions src/t2-design/components/Service.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import _ from 'lodash';

import { Card, Icon } from 'semantic-ui-react'

Expand All @@ -19,11 +17,27 @@ const Service = (props) => (
<Card.Content textAlign="left">
<Icon name={props.icon} className="floatleft" size="big"/>
<Card.Header>{props.name}</Card.Header>
<Card.Meta>Service / Deployment / Build</Card.Meta>
<Card.Meta>{serviceType(props)}</Card.Meta>
</Card.Content>
</Card></Item>
);

const serviceType = (props) => {
var type;
if (props.hasBuildConfig || (props.services && props.services.length > 0)) {
type = [<span key="dc" title="DeploymentConfig">DC</span>];
if (props.hasBuildConfig) {
type = [...type, " / ", <span key="bc" title="BuildConfig">BC</span>];
}
if (props.services && props.services.length > 0) {
type = ["Services / ", type];
}
} else {
type = "DeploymentConfig"
}
return type;
};

Service.propTypes = {
name: PropTypes.string.isRequired,
icon: PropTypes.string.isRequired,
Expand Down
2 changes: 0 additions & 2 deletions src/t2-design/components/Storage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import IconItem from "./IconItem";

Expand Down
5 changes: 3 additions & 2 deletions src/t2-design/components/Topology.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.topo {
display: flex;
height: 500px; /* TEMP please change */
height: 100%;
overflow: auto;
}

.topo-service-stack {
Expand All @@ -16,7 +17,7 @@
}

.topo .topo-service-stack .internals {
height: 120px !important;
height: 160px !important;
}

.topo .topo-svg {
Expand Down
Loading

0 comments on commit a80e788

Please sign in to comment.