2018-02-01 12:38:12 +02:00
|
|
|
/* eslint-disable camelcase */
|
2018-01-08 21:08:01 +02:00
|
|
|
import React from 'react';
|
|
|
|
import { Margin } from 'styled-components-spacing';
|
2018-01-12 19:40:23 +02:00
|
|
|
import ReduxForm from 'declarative-redux-form';
|
|
|
|
import { stopSubmit, destroy } from 'redux-form';
|
|
|
|
import { connect } from 'react-redux';
|
2018-01-18 16:46:49 +02:00
|
|
|
import { destroyAll } from 'react-redux-values';
|
2018-01-12 19:40:23 +02:00
|
|
|
import { graphql, compose } from 'react-apollo';
|
|
|
|
import intercept from 'apr-intercept';
|
|
|
|
import constantCase from 'constant-case';
|
|
|
|
import get from 'lodash.get';
|
|
|
|
import omit from 'lodash.omit';
|
|
|
|
import uniqBy from 'lodash.uniqby';
|
2018-01-08 21:08:01 +02:00
|
|
|
|
2018-01-15 19:34:15 +02:00
|
|
|
import { ViewContainer, H2, Button } from 'joyent-ui-toolkit';
|
2018-01-08 21:08:01 +02:00
|
|
|
|
|
|
|
import Name from '@containers/create-instance/name';
|
2018-01-09 20:14:20 +02:00
|
|
|
import Image from '@containers/create-instance/image';
|
2018-01-11 15:27:16 +02:00
|
|
|
import Package from '@containers/create-instance/package';
|
2018-01-09 17:59:04 +02:00
|
|
|
import Tags from '@containers/create-instance/tags';
|
|
|
|
import Metadata from '@containers/create-instance/metadata';
|
2018-01-19 19:37:31 +02:00
|
|
|
import UserScript from '@containers/create-instance/user-script';
|
2018-01-11 17:54:24 +02:00
|
|
|
import Networks from '@containers/create-instance/networks';
|
2018-01-09 17:59:04 +02:00
|
|
|
import Firewall from '@containers/create-instance/firewall';
|
2018-01-11 22:26:42 +02:00
|
|
|
import CNS from '@containers/create-instance/cns';
|
2018-01-09 17:59:04 +02:00
|
|
|
import Affinity from '@containers/create-instance/affinity';
|
2018-01-12 19:40:23 +02:00
|
|
|
import CreateInstanceMutation from '@graphql/create-instance.gql';
|
|
|
|
import parseError from '@state/parse-error';
|
2018-01-08 21:08:01 +02:00
|
|
|
|
2018-01-16 13:23:00 +02:00
|
|
|
const CREATE_FORM = 'CREATE-INSTANCE';
|
|
|
|
|
2018-01-18 16:46:49 +02:00
|
|
|
const CreateInstance = ({ step, disabled, handleSubmit, history, match }) => (
|
2018-01-08 21:08:01 +02:00
|
|
|
<ViewContainer>
|
|
|
|
<Margin top={4} bottom={4}>
|
|
|
|
<H2>Create Instances</H2>
|
|
|
|
</Margin>
|
2018-02-01 17:33:58 +02:00
|
|
|
<Name
|
|
|
|
history={history}
|
|
|
|
match={match}
|
|
|
|
step="name"
|
|
|
|
expanded={step === 'name'}
|
|
|
|
/>
|
|
|
|
<Image
|
|
|
|
history={history}
|
|
|
|
match={match}
|
|
|
|
step="image"
|
|
|
|
expanded={step === 'image'}
|
|
|
|
/>
|
|
|
|
<Package
|
|
|
|
history={history}
|
|
|
|
match={match}
|
|
|
|
step="package"
|
|
|
|
expanded={step === 'package'}
|
|
|
|
/>
|
|
|
|
<Tags
|
|
|
|
history={history}
|
|
|
|
match={match}
|
|
|
|
step="tags"
|
|
|
|
expanded={step === 'tags'}
|
|
|
|
/>
|
|
|
|
<Metadata
|
|
|
|
history={history}
|
|
|
|
match={match}
|
|
|
|
step="metadata"
|
|
|
|
expanded={step === 'metadata'}
|
|
|
|
/>
|
2018-01-30 18:04:03 +02:00
|
|
|
<UserScript
|
|
|
|
history={history}
|
|
|
|
match={match}
|
|
|
|
step="user-script"
|
|
|
|
expanded={step === 'user-script'}
|
|
|
|
/>
|
2018-02-01 17:33:58 +02:00
|
|
|
<Networks
|
|
|
|
history={history}
|
|
|
|
match={match}
|
|
|
|
step="networks"
|
|
|
|
expanded={step === 'networks'}
|
|
|
|
/>
|
|
|
|
<Firewall
|
|
|
|
history={history}
|
|
|
|
match={match}
|
|
|
|
step="firewall"
|
|
|
|
expanded={step === 'firewall'}
|
|
|
|
/>
|
2018-01-30 18:04:03 +02:00
|
|
|
<CNS history={history} match={match} step="cns" expanded={step === 'cns'} />
|
2018-02-01 17:33:58 +02:00
|
|
|
<Affinity
|
|
|
|
history={history}
|
|
|
|
match={match}
|
|
|
|
step="affinity"
|
|
|
|
expanded={step === 'affinity'}
|
|
|
|
/>
|
2018-01-12 17:25:26 +02:00
|
|
|
<Margin top={7} bottom={10}>
|
2018-01-16 13:23:00 +02:00
|
|
|
<ReduxForm form={CREATE_FORM} onSubmit={handleSubmit}>
|
2018-01-12 19:40:23 +02:00
|
|
|
{({ handleSubmit, submitting }) => (
|
|
|
|
<form onSubmit={handleSubmit}>
|
2018-01-18 16:46:49 +02:00
|
|
|
<Button disabled={disabled} loading={submitting}>
|
2018-01-12 19:40:23 +02:00
|
|
|
Deploy
|
|
|
|
</Button>
|
|
|
|
</form>
|
|
|
|
)}
|
|
|
|
</ReduxForm>
|
2018-01-12 17:25:26 +02:00
|
|
|
</Margin>
|
2018-01-08 21:08:01 +02:00
|
|
|
</ViewContainer>
|
|
|
|
);
|
2018-01-12 19:40:23 +02:00
|
|
|
|
|
|
|
export default compose(
|
|
|
|
graphql(CreateInstanceMutation, { name: 'createInstance' }),
|
2018-01-19 19:37:31 +02:00
|
|
|
connect(({ form, values }, { match }) => {
|
2018-02-09 15:14:19 +02:00
|
|
|
const FORM_NAME = 'create-instance-name';
|
2018-01-19 19:37:31 +02:00
|
|
|
const step = get(match, 'params.step', 'name');
|
2018-02-09 15:14:19 +02:00
|
|
|
const nameFilled = get(form, `${FORM_NAME}.values.name`, '');
|
2018-01-19 19:37:31 +02:00
|
|
|
|
2018-01-18 16:46:49 +02:00
|
|
|
const disabled = ['name', 'image', 'package', 'networks'].some(
|
2018-02-09 15:14:19 +02:00
|
|
|
step => !get(values, `create-instance-${step}-proceeded`, false) || !nameFilled.length
|
2018-01-18 16:46:49 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
if (disabled) {
|
2018-01-19 19:37:31 +02:00
|
|
|
return { disabled, step };
|
2018-01-18 16:46:49 +02:00
|
|
|
}
|
|
|
|
|
2018-02-01 17:33:58 +02:00
|
|
|
const name = get(
|
|
|
|
form,
|
|
|
|
'create-instance-name.values.name',
|
|
|
|
'<instance-name>'
|
|
|
|
);
|
2018-01-12 19:40:23 +02:00
|
|
|
|
2018-02-01 17:33:58 +02:00
|
|
|
const firewall_enabled = get(
|
|
|
|
form,
|
|
|
|
'CREATE-INSTANCE-FIREWALL.values.enabled',
|
|
|
|
false
|
|
|
|
);
|
2018-01-12 19:40:23 +02:00
|
|
|
|
2018-02-01 17:33:58 +02:00
|
|
|
const image = get(
|
|
|
|
form,
|
|
|
|
'create-instance-image.values.image',
|
|
|
|
'<instance-image>'
|
|
|
|
);
|
2018-01-12 19:40:23 +02:00
|
|
|
|
2018-02-01 17:33:58 +02:00
|
|
|
const pkg = get(
|
|
|
|
form,
|
|
|
|
'create-instance-package.values.package',
|
|
|
|
'<instance-pkg>'
|
|
|
|
);
|
2018-01-12 19:40:23 +02:00
|
|
|
|
2018-01-18 16:46:49 +02:00
|
|
|
const networks = get(form, 'CREATE-INSTANCE-NETWORKS.values', {});
|
2018-01-12 19:40:23 +02:00
|
|
|
|
|
|
|
const metadata = get(values, 'create-instance-metadata', []);
|
|
|
|
const receivedTags = get(values, 'create-instance-tags', []);
|
|
|
|
const affinity = get(values, 'create-instance-affinity', []);
|
|
|
|
const cns = get(values, 'create-instance-cns-enabled', true);
|
|
|
|
const cnsServices = get(values, 'create-instance-cns-services', null);
|
2018-01-19 19:37:31 +02:00
|
|
|
const userScript = get(values, 'create-instance-user-script', {});
|
2018-01-12 19:40:23 +02:00
|
|
|
|
|
|
|
const tags = receivedTags.map(a => omit(a, 'expanded'));
|
|
|
|
|
|
|
|
tags.push({ name: 'triton.cns.disable', value: !cns });
|
|
|
|
|
|
|
|
if (cnsServices && cns) {
|
|
|
|
tags.push({ name: 'triton.cns.services', value: cnsServices.join(',') });
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
forms: Object.keys(form), // improve this
|
2018-01-18 16:46:49 +02:00
|
|
|
name,
|
2018-01-12 19:40:23 +02:00
|
|
|
pkg,
|
|
|
|
image,
|
2018-01-18 16:46:49 +02:00
|
|
|
affinity,
|
|
|
|
metadata,
|
2018-01-19 19:37:31 +02:00
|
|
|
userScript,
|
2018-01-18 16:46:49 +02:00
|
|
|
tags,
|
|
|
|
firewall_enabled,
|
|
|
|
networks,
|
2018-01-19 19:37:31 +02:00
|
|
|
disabled,
|
|
|
|
step
|
2018-01-12 19:40:23 +02:00
|
|
|
};
|
|
|
|
}),
|
|
|
|
connect(null, (dispatch, ownProps) => {
|
|
|
|
const {
|
|
|
|
name,
|
|
|
|
pkg,
|
|
|
|
image,
|
|
|
|
affinity,
|
|
|
|
metadata,
|
2018-01-19 19:37:31 +02:00
|
|
|
userScript,
|
2018-01-12 19:40:23 +02:00
|
|
|
tags,
|
|
|
|
firewall_enabled,
|
|
|
|
networks,
|
|
|
|
forms,
|
|
|
|
createInstance,
|
|
|
|
history
|
|
|
|
} = ownProps;
|
|
|
|
|
|
|
|
return {
|
|
|
|
handleSubmit: async () => {
|
2018-01-18 16:46:49 +02:00
|
|
|
const _affinity = affinity
|
|
|
|
.map(aff => ({
|
|
|
|
conditional: aff['rule-instance-conditional'],
|
|
|
|
placement: aff['rule-instance-placement'],
|
|
|
|
identity: aff['rule-type'],
|
|
|
|
key: aff['rule-instance-tag-key'],
|
|
|
|
pattern: aff['rule-instance-tag-value-pattern'],
|
|
|
|
value:
|
|
|
|
aff['rule-type'] === 'name'
|
|
|
|
? aff['rule-instance-name']
|
|
|
|
: aff['rule-instance-tag-value']
|
|
|
|
}))
|
|
|
|
.map(({ conditional, placement, identity, key, pattern, value }) => {
|
|
|
|
const type = constantCase(
|
|
|
|
`${conditional}_${placement === 'same' ? 'equal' : 'not_equal'}`
|
|
|
|
);
|
|
|
|
|
|
|
|
const patterns = {
|
|
|
|
equalling: value => value,
|
|
|
|
'not-equalling': value => `/^!${value}$/`,
|
|
|
|
containing: value => `/${value}/`,
|
|
|
|
starting: value => `/^${value}/`,
|
|
|
|
ending: value => `/${value}$/`
|
|
|
|
};
|
|
|
|
|
|
|
|
const _key = identity === 'name' ? 'instance' : key;
|
|
|
|
const _value = patterns[pattern](value);
|
|
|
|
|
|
|
|
return {
|
|
|
|
type,
|
|
|
|
key: _key,
|
|
|
|
value: _value
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
2018-01-19 19:37:31 +02:00
|
|
|
const _name = name.toLowerCase();
|
2018-01-24 13:55:04 +02:00
|
|
|
const _metadata = metadata.map(a => omit(a, 'open'));
|
|
|
|
const _tags = uniqBy(tags, 'name').map(a => omit(a, 'expanded'));
|
2018-02-01 17:33:58 +02:00
|
|
|
const _networks = Object.keys(networks).filter(
|
|
|
|
network => networks[network]
|
|
|
|
);
|
2018-01-19 19:37:31 +02:00
|
|
|
|
|
|
|
if (userScript && userScript.value) {
|
|
|
|
_metadata.push({ name: 'user-script', value: userScript.value });
|
|
|
|
}
|
2018-01-18 16:46:49 +02:00
|
|
|
|
2018-01-12 19:40:23 +02:00
|
|
|
const [err, res] = await intercept(
|
|
|
|
createInstance({
|
|
|
|
variables: {
|
2018-01-18 16:46:49 +02:00
|
|
|
name: _name,
|
2018-01-12 19:40:23 +02:00
|
|
|
package: pkg,
|
|
|
|
image,
|
2018-01-24 16:16:47 +02:00
|
|
|
affinity: _affinity.length ? _affinity : undefined,
|
2018-01-18 16:46:49 +02:00
|
|
|
metadata: _metadata,
|
|
|
|
tags: _tags,
|
2018-01-12 19:40:23 +02:00
|
|
|
firewall_enabled,
|
2018-01-24 16:16:47 +02:00
|
|
|
networks: _networks.length ? _networks : undefined
|
2018-01-12 19:40:23 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
return dispatch(
|
2018-01-16 13:23:00 +02:00
|
|
|
stopSubmit(CREATE_FORM, {
|
2018-01-12 19:40:23 +02:00
|
|
|
_error: parseError(err)
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-01-18 16:46:49 +02:00
|
|
|
dispatch([destroyAll(), forms.map(name => destroy(name))]);
|
2018-01-12 19:40:23 +02:00
|
|
|
|
|
|
|
history.push(`/instances/${res.data.createMachine.name}`);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
})
|
|
|
|
)(CreateInstance);
|