Skip to content

Commit

Permalink
services: Make env vars configurable with defaults
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Northey <ryan@synca.io>
  • Loading branch information
phlax committed Nov 25, 2020
1 parent dc52dfd commit 75ebc98
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 156 deletions.
18 changes: 10 additions & 8 deletions control/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,24 +122,26 @@ async def handle_image(self, ws, event):

async def add_service(self, request: Request) -> Response:
data = await self.load_json(request)
data['service_config'] = self.service_types[data["service_type"]]
service_config = self.service_types[data["service_type"]]

if not await self.client.image_exists(data['service_config']['image']):
await self.client.pull_image(data['service_config']['image'])
data['image'] = service_config.get("image")
if not await self.client.image_exists(data['image']):
await self.client.pull_image(data['image'])

config_path = data['service_config']['labels'].get('envoy.playground.config.path')
config_path = service_config['labels'].get('envoy.playground.config.path')
if config_path:
config_dir = os.path.dirname(config_path)
config_fname = os.path.basename(config_path)
data['mounts'] = {
config_dir: await self.populate_volume(
data['mounts'] = OrderedDict(
(config_dir, await self.populate_volume(
'service',
data['name'],
'config',
{config_fname: base64.b64encode(
data.pop("configuration", "").encode('utf-8')).decode()})}
data.pop("configuration", "").encode('utf-8')).decode()}), ))
else:
data['mounts'] = {}
data['mounts'] = OrderedDict()
data['environment'] = data.pop('vars')
await self.client.create_service(**data)
return self.dump_json(dict(message="OK"))

Expand Down
9 changes: 4 additions & 5 deletions control/connectors/docker/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,19 +197,18 @@ async def pull_image(self, image_tag: str) -> None:
async def create_service(
self,
name: str,
service_config: dict,
environment: OrderedDict,
image: str,
service_type: str,
mounts: dict,
mounts: OrderedDict,
aliases=None) -> None:
image = service_config.get("image")
if not image:
# todo: add build logic
return
environment = [
"%s=%s" % (k, v)
for k, v
in service_config.get("environment", {}).items()]

in environment.items()]
container = await self.client.containers.create_or_replace(
config=self._get_service_config(
service_type,
Expand Down
10 changes: 1 addition & 9 deletions services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,7 @@ services:
http-echo:
image: mendhak/http-https-echo
labels:
envoy.playground.service: "HTTP echo"
envoy.playground.service: "HTTP/S echo"
envoy.playground.logo: "http-echo.svg"
environment:
HTTPS_PORT: 0

https-echo:
image: mendhak/http-https-echo
labels:
envoy.playground.service: "HTTPS echo"
envoy.playground.logo: "https-echo.svg"
environment:
HTTP_PORT: 0
131 changes: 0 additions & 131 deletions services/https-echo/https-echo.svg

This file was deleted.

156 changes: 155 additions & 1 deletion ui/src/service/forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import exact from 'prop-types-exact';

import {connect} from 'react-redux';

import {Col, CustomInput, Input} from 'reactstrap';
import {Button, Col, CustomInput, Input, Row} from 'reactstrap';

import Editor from 'react-simple-code-editor';
import {highlight, languages} from 'prismjs/components/prism-core';
Expand All @@ -17,6 +17,8 @@ import {

import {updateForm} from '../app/store';

import {ActionRemove} from '../shared/actions';


class BaseServiceForm extends React.PureComponent {
static propTypes = exact({
Expand Down Expand Up @@ -171,3 +173,155 @@ const mapStateToProps = function(state, other) {

const ServiceConfigurationForm = connect(mapStateToProps)(BaseServiceConfigurationForm);
export {ServiceConfigurationForm};


export class ServiceEnvironmentListForm extends React.PureComponent {
static propTypes = exact({
vars: PropTypes.array,
});

render () {
const {vars={}} = this.props;
const onDelete = null;
const title = '';
return (
<Row className="mt-2 pb-3">
<Col>
<Row className="pl-5 pr-5">
<Col sm={1} className="m-0 p-0">
<div className="p-1 bg-dark">
<span>&nbsp;</span>
</div>
</Col>
<Col sm={6} className="m-0 p-0">
<div className="p-1 bg-dark">
Variable name
</div>
</Col>
<Col sm={5} className="m-0 p-0">
<div className="p-1 bg-dark">
Variable value
</div>
</Col>
</Row>
{Object.entries(vars).map(([k, v], index) => {
return (
<Row key={index} className="pl-5 pr-5">
<Col sm={1} className="m-0 p-0">
<div className="p-2 bg-white">
<ActionRemove
title={title}
name={title}
remove={evt => this.onDelete(evt, onDelete)} />
</div>
</Col>
<Col sm={6} className="m-0 p-0 border-bottom">
<div className="p-2 bg-white">
{k}
</div>
</Col>
<Col sm={5} className="m-0 p-0 border-bottom">
<div className="p-2 bg-white">
{v + ''}
</div>
</Col>
</Row>);
})}
</Col>
</Row>);
}
}


export class BaseServiceEnvironmentForm extends React.Component {
static propTypes = exact({
dispatch: PropTypes.func,
form: PropTypes.object.isRequired,
});

state = {value: '', network: ''};

onClick = async (evt) => {
const {value, key} = this.state;
const {dispatch, form} = this.props;
const {vars: _vars={}} = form;
const vars = {..._vars};
vars[key] = value;
this.setState({value: '', key: ''});
await dispatch(updateForm({vars}));
}

onChange = (evt) => {
const update = {};
update[evt.target.name] = evt.target.value;
this.setState({...update});
}

get messages () {
return [
"Add network vars for your proxy.",
"Your proxy will be addressable by other proxies or services with this value",
"You can restrict which networks an value is used for with a glob match, default is *",
];
}

async componentDidUpdate(prevProps) {
const {dispatch, service_type, service_types} = this.props;
if (service_type !== prevProps.service_type) {
const {environment: vars} = service_types[service_type];
await dispatch(updateForm({vars}));
}
}

render () {
const {value, key} = this.state;
const {form} = this.props;
const {vars={}} = form;
return (
<PlaygroundForm messages={this.messages}>
<PlaygroundFormGroup>
<PlaygroundFormGroupRow
label="value"
title="Add value">
<Col sm={3}>
<Input
type="text"
onChange={this.onChange}
value={key}
id="key"
name="key"
placeholder="Variable name" />
</Col>
<Col sm={4}>
<Input
type="text"
onChange={this.onChange}
value={value}
id="value"
name="value"
placeholder="Variable value" />
</Col>
<Col sm={2}>
<Button
color="success"
onClick={this.onClick}>+</Button>
</Col>
</PlaygroundFormGroupRow>
<ServiceEnvironmentListForm vars={{...vars}} />
</PlaygroundFormGroup>
</PlaygroundForm>
);
}
}


const mapEnvFormStateToProps = function(state) {
return {
form: state.form.value,
service_types: state.service_type.value,
};
}


const ServiceEnvironmentForm = connect(mapEnvFormStateToProps)(BaseServiceEnvironmentForm);
export {ServiceEnvironmentForm}
6 changes: 4 additions & 2 deletions ui/src/service/modals.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import exact from 'prop-types-exact';

import {ServiceConfigurationForm, ServiceForm} from './forms';
import {ServiceConfigurationForm, ServiceEnvironmentForm, ServiceForm} from './forms';

import {connect} from 'react-redux';

Expand Down Expand Up @@ -145,7 +145,9 @@ export class BaseServiceModal extends React.Component {
const {form, service_types} = this.props;
const {service_type} = form;
let showConfig = false;
const tabs = {Service: <ServiceForm />};
const tabs = {
Service: <ServiceForm />,
Environment: <ServiceEnvironmentForm service_type={service_type} />};
if (service_type) {
const {configuration} = service_types[service_type];
const configPath = service_types[service_type]['labels']['envoy.playground.config.path'];
Expand Down

0 comments on commit 75ebc98

Please sign in to comment.