diff --git a/packages/my-joy-beta/src/components/create-instance/affinity.js b/packages/my-joy-beta/src/components/create-instance/affinity.js index 089403f9..68f33416 100644 --- a/packages/my-joy-beta/src/components/create-instance/affinity.js +++ b/packages/my-joy-beta/src/components/create-instance/affinity.js @@ -11,7 +11,7 @@ const Values = ( diff --git a/packages/my-joy-beta/src/components/create-instance/firewall.js b/packages/my-joy-beta/src/components/create-instance/firewall.js index 491de096..28b0571a 100644 --- a/packages/my-joy-beta/src/components/create-instance/firewall.js +++ b/packages/my-joy-beta/src/components/create-instance/firewall.js @@ -50,7 +50,7 @@ const parsePartial = (p, index) => { return ; } -} +}; const Rule = ({ enabled, rule_obj }) => { const { action, protocol } = rule_obj; @@ -65,23 +65,27 @@ const Rule = ({ enabled, rule_obj }) => { - From:{' '} + From: + + + {froms} - {froms} - To:{' '} + To: + + + {tos} - {tos} - Protocol:{' '} + Protocol: {protocol.name} @@ -89,7 +93,7 @@ const Rule = ({ enabled, rule_obj }) => { - Ports:{' '} + Ports: {protocol.targets.join(';')} @@ -97,7 +101,7 @@ const Rule = ({ enabled, rule_obj }) => { - Action:{' '} + Action: {constantCase(action)} diff --git a/packages/my-joy-beta/src/containers/create-instance/firewall.js b/packages/my-joy-beta/src/containers/create-instance/firewall.js index 2c4e07a9..178af85d 100644 --- a/packages/my-joy-beta/src/containers/create-instance/firewall.js +++ b/packages/my-joy-beta/src/containers/create-instance/firewall.js @@ -58,8 +58,7 @@ const Firewall = ({ tagRules={tagRules} enabled={enabled} /> - ) : null - } + ) : null} ) : 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', []) diff --git a/packages/my-joy-beta/src/containers/create-instance/index.js b/packages/my-joy-beta/src/containers/create-instance/index.js index f9b1e416..a33c7ab9 100644 --- a/packages/my-joy-beta/src/containers/create-instance/index.js +++ b/packages/my-joy-beta/src/containers/create-instance/index.js @@ -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 }) => (

Create Instances

@@ -50,9 +61,157 @@ export default ({ step, ...props }) => ( ) : null} - + + {({ handleSubmit, submitting }) => ( +
+ +
+ )} +
); + +export default compose( + graphql(CreateInstanceMutation, { name: 'createInstance' }), + connect(({ form, values }, ownProps) => { + const name = get( + form, + 'create-instance-name.values.name', + '' + ); + + const firewall = get( + form, + 'CREATE-INSTANCE-FIREWALL.values.enabled', + false + ); + + const image = get( + form, + 'create-instance-image.values.image', + '' + ); + + const pkg = get( + form, + 'create-instance-package.values.package', + '' + ); + + const networks = get( + form, + 'CREATE-INSTANCE-NETWORKS.values', + '' + ); + + 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); diff --git a/packages/my-joy-beta/src/containers/instances/snapshots.js b/packages/my-joy-beta/src/containers/instances/snapshots.js index edb5723c..12b09597 100644 --- a/packages/my-joy-beta/src/containers/instances/snapshots.js +++ b/packages/my-joy-beta/src/containers/instances/snapshots.js @@ -150,7 +150,6 @@ const Snapshots = ({ }; export default compose( - withRouter, graphql(StartSnapshot, { name: 'start' }), graphql(RemoveSnapshot, { name: 'remove' }), graphql(CreateSnapshotMutation, { name: 'createSnapshot' }), diff --git a/packages/my-joy-beta/src/graphql/create-instance.gql b/packages/my-joy-beta/src/graphql/create-instance.gql new file mode 100644 index 00000000..48b5465b --- /dev/null +++ b/packages/my-joy-beta/src/graphql/create-instance.gql @@ -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 + } + } +}