feat(my-joy-beta): create instance submit

fixes #989

# Conflicts:
#	packages/my-joy-beta/src/containers/create-instance/index.js
This commit is contained in:
Sérgio Ramos 2018-01-12 17:40:23 +00:00
parent 54d4b61250
commit 9432bfd1a3
6 changed files with 218 additions and 19 deletions

View File

@ -11,7 +11,7 @@ const Values = (
<Margin right={1}>
<Select embedded>
<option value="equalling">equalling</option>
<option value="!equalling">not equalling</option>
<option value="not-equalling">not equalling</option>
<option value="containing">containing</option>
<option value="starting">starting with</option>
<option value="ending">ending with</option>
@ -51,9 +51,6 @@ export const Rule = rule => (
</FormGroup>
{rule['rule-type'] === 'tag' ? (
<Fragment>
<FormGroup name="rule-instance-tag-key-pattern" field={Field}>
{Values}
</FormGroup>
<FormGroup name="rule-instance-tag-key" field={Field}>
<Input small embedded type="text" required placeholder="key" />
</FormGroup>

View File

@ -50,7 +50,7 @@ const parsePartial = (p, index) => {
return <Tag key={index} name={name} value={value} />;
}
}
};
const Rule = ({ enabled, rule_obj }) => {
const { action, protocol } = rule_obj;
@ -65,23 +65,27 @@ const Rule = ({ enabled, rule_obj }) => {
<Col xs={3}>
<Flex justifyStart alignCenter contentStretch>
<FlexItem>
<b>From:{' '}</b>
<b>From: </b>
</FlexItem>
<FlexItem grow={1}>
<TagList>{froms}</TagList>
</FlexItem>
<FlexItem grow={1}><TagList>{froms}</TagList></FlexItem>
</Flex>
</Col>
<Col xs={3}>
<Flex justifyStart alignCenter contentStretch>
<FlexItem>
<b>To:{' '}</b>
<b>To: </b>
</FlexItem>
<FlexItem grow={1}>
<TagList>{tos}</TagList>
</FlexItem>
<FlexItem grow={1}><TagList>{tos}</TagList></FlexItem>
</Flex>
</Col>
<Col xs={2}>
<Flex justifyStart alignCenter contentStretch>
<FlexItem>
<b>Protocol:{' '}</b>
<b>Protocol: </b>
</FlexItem>
<FlexItem grow={1}>{protocol.name}</FlexItem>
</Flex>
@ -89,7 +93,7 @@ const Rule = ({ enabled, rule_obj }) => {
<Col xs={2}>
<Flex justifyStart alignCenter contentStretch>
<FlexItem>
<b>Ports:{' '}</b>
<b>Ports: </b>
</FlexItem>
<FlexItem grow={1}>{protocol.targets.join(';')}</FlexItem>
</Flex>
@ -97,7 +101,7 @@ const Rule = ({ enabled, rule_obj }) => {
<Col xs={2}>
<Flex justifyStart alignCenter contentStretch>
<FlexItem>
<b>Action:{' '}</b>
<b>Action: </b>
</FlexItem>
<FlexItem grow={1}>{constantCase(action)}</FlexItem>
</Flex>

View File

@ -58,8 +58,7 @@ const Firewall = ({
tagRules={tagRules}
enabled={enabled}
/>
) : null
}
) : null}
</ReduxForm>
) : null}
{proceeded && !expanded ? (
@ -85,6 +84,7 @@ export default compose(
connect(
({ form, values }, ownProps) => ({
...ownProps,
proceeded: get(values, 'create-instance-firewall-proceeded', false),
enabled: get(form, `${FORM_NAME}.values.enabled`, false),
showInactive: get(form, `${FORM_NAME}.values.show-inactive`, false),
tags: get(values, 'create-instance-tags', [])

View File

@ -1,6 +1,15 @@
import React from 'react';
import { Margin } from 'styled-components-spacing';
import ReduxForm from 'declarative-redux-form';
import { stopSubmit, destroy } from 'redux-form';
import remcalc from 'remcalc';
import { connect } from 'react-redux';
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';
import { ViewContainer, H2, Button, Divider } from 'joyent-ui-toolkit';
@ -13,8 +22,10 @@ import Networks from '@containers/create-instance/networks';
import Firewall from '@containers/create-instance/firewall';
import CNS from '@containers/create-instance/cns';
import Affinity from '@containers/create-instance/affinity';
import CreateInstanceMutation from '@graphql/create-instance.gql';
import parseError from '@state/parse-error';
export default ({ step, ...props }) => (
const CreateInstance = ({ step, handleSubmit, ...props }) => (
<ViewContainer>
<Margin top={4} bottom={4}>
<H2>Create Instances</H2>
@ -50,9 +61,157 @@ export default ({ step, ...props }) => (
<Divider height={remcalc(1)} />
) : null}
<Margin top={7} bottom={10}>
<Button disabled={step !== 'done'} onClick={() => console.log('DONE')}>
<ReduxForm form="create-instance" onSubmit={handleSubmit}>
{({ handleSubmit, submitting }) => (
<form onSubmit={handleSubmit}>
<Button disabled={step !== 'done'} loading={submitting}>
Deploy
</Button>
</form>
)}
</ReduxForm>
</Margin>
</ViewContainer>
);
export default compose(
graphql(CreateInstanceMutation, { name: 'createInstance' }),
connect(({ form, values }, ownProps) => {
const name = get(
form,
'create-instance-name.values.name',
'<instance-name>'
);
const firewall = get(
form,
'CREATE-INSTANCE-FIREWALL.values.enabled',
false
);
const image = get(
form,
'create-instance-image.values.image',
'<instance-image>'
);
const pkg = get(
form,
'create-instance-package.values.package',
'<instance-image>'
);
const networks = get(
form,
'CREATE-INSTANCE-NETWORKS.values',
'<instance-image>'
);
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);
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(',') });
}
const affRules = 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}$/`,
containing: `/${value}/`,
starting: `/^${value}/`,
ending: `/${value}$/`
};
const _key = identity === 'name' ? 'instance' : key;
const _value = patterns[pattern](value);
return {
type,
key: _key,
value: _value
};
});
return {
forms: Object.keys(form), // improve this
name: name.toLowerCase(),
pkg,
image,
affinity: affRules,
metadata: metadata.map(a => omit(a, 'expanded')),
tags: uniqBy(tags, 'name'),
firewall_enabled: firewall,
networks: Object.keys(networks).filter(network => networks[network])
};
}),
connect(null, (dispatch, ownProps) => {
const {
name,
pkg,
image,
affinity,
metadata,
tags,
firewall_enabled,
networks,
forms,
createInstance,
history
} = ownProps;
return {
handleSubmit: async () => {
const [err, res] = await intercept(
createInstance({
variables: {
name,
package: pkg,
image,
affinity,
metadata,
tags,
firewall_enabled,
networks
}
})
);
if (err) {
return dispatch(
stopSubmit(TABLE_FORM_NAME, {
_error: parseError(err)
})
);
}
dispatch(forms.map(name => destroy(name)));
history.push(`/instances/${res.data.createMachine.name}`);
}
};
})
)(CreateInstance);

View File

@ -150,7 +150,6 @@ const Snapshots = ({
};
export default compose(
withRouter,
graphql(StartSnapshot, { name: 'start' }),
graphql(RemoveSnapshot, { name: 'remove' }),
graphql(CreateSnapshotMutation, { name: 'createSnapshot' }),

View File

@ -0,0 +1,40 @@
mutation createInstance(
$name: String!
$package: ID!
$image: ID!
$networks: [ID]
$affinity: [AffinityRule]
$metadata: [KeyValueInput]
$tags: [KeyValueInput]
$firewall_enabled: Boolean
) {
createMachine(
name: $name
package: $package
image: $image
networks: $networks
affinity: $affinity
metadata: $metadata
tags: $tags
firewall_enabled: $firewall_enabled
) {
id
state
brand
name
created
updated
primary_ip
ips
docker
dns_names
compute_node
image {
id
name
}
package {
name
}
}
}