From 54d4b61250d40557a285789c1d12d2fff5d89192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Tue, 9 Jan 2018 15:59:04 +0000 Subject: [PATCH] feat(my-joy-beta): create instance firewall fixes #986 --- .../__tests__/__snapshots__/cns.spec.js.snap | 1 + .../src/components/create-instance/cns.js | 2 +- .../components/create-instance/firewall.js | 161 ++++++++++++++++++ .../__snapshots__/networks.spec.js.snap | 57 +++---- .../containers/create-instance/firewall.js | 142 +++++++++++++++ .../src/containers/create-instance/index.js | 10 +- .../containers/create-instance/networks.js | 6 +- .../my-joy-beta/src/graphql/list-fw-rules.gql | 10 ++ 8 files changed, 349 insertions(+), 40 deletions(-) create mode 100644 packages/my-joy-beta/src/components/create-instance/firewall.js create mode 100644 packages/my-joy-beta/src/containers/create-instance/firewall.js create mode 100644 packages/my-joy-beta/src/graphql/list-fw-rules.gql diff --git a/packages/my-joy-beta/src/components/create-instance/__tests__/__snapshots__/cns.spec.js.snap b/packages/my-joy-beta/src/components/create-instance/__tests__/__snapshots__/cns.spec.js.snap index a8295c4c..80a85cbb 100644 --- a/packages/my-joy-beta/src/components/create-instance/__tests__/__snapshots__/cns.spec.js.snap +++ b/packages/my-joy-beta/src/components/create-instance/__tests__/__snapshots__/cns.spec.js.snap @@ -782,6 +782,7 @@ exports[`renders without throwing 1`] = ` Instance name hostname + s
( : network ? 'Network' : service ? 'CNS service' : 'Instance name'}{' '} - hostname + hostname{values.length === 1 ? '' : 's'} diff --git a/packages/my-joy-beta/src/components/create-instance/firewall.js b/packages/my-joy-beta/src/components/create-instance/firewall.js new file mode 100644 index 00000000..491de096 --- /dev/null +++ b/packages/my-joy-beta/src/components/create-instance/firewall.js @@ -0,0 +1,161 @@ +import React, { Fragment } from 'react'; +import { Field } from 'redux-form'; +import { Margin, Padding } from 'styled-components-spacing'; +import Flex, { FlexItem } from 'styled-flex-component'; +import styled from 'styled-components'; +import remcalc from 'remcalc'; +import constantCase from 'constant-case'; + +import { + NameIcon, + H3, + P, + FormGroup, + FormLabel, + Input, + FormMeta, + Button, + Toggle, + Card, + CardOutlet, + Divider, + Row, + Col, + TagList +} from 'joyent-ui-toolkit'; + +import Tag from '@components/instances/tags'; +import Title from './title'; + +const Box = styled.div` + display: inline-block; + background-color: ${props => props.theme.white}; + border: ${remcalc(1)} solid ${props => props.theme.grey}; + min-width: 100%; +`; + +const Wildcards = { + vmall: 'All VMs in DC', + any: 'Any' +}; + +const parsePartial = (p, index) => { + if (p[0] === 'wildcard') { + return {Wildcards[p[1]]}; + } + + if (p[0] === 'tag') { + const value = Array.isArray(p[1]) ? p[1][1] : ''; + const name = Array.isArray(p[1]) ? p[1][0] : p[1]; + + return ; + } +} + +const Rule = ({ enabled, rule_obj }) => { + const { action, protocol } = rule_obj; + + const froms = rule_obj.from.map(parsePartial); + const tos = rule_obj.to.map(parsePartial); + + return ( + + + + + + + From:{' '} + + {froms} + + + + + + To:{' '} + + {tos} + + + + + + Protocol:{' '} + + {protocol.name} + + + + + + Ports:{' '} + + {protocol.targets.join(';')} + + + + + + Action:{' '} + + {constantCase(action)} + + + + + + ); +}; + +export default ({ + defaultRules = [], + tagRules = [], + enabled = false, + handleSubmit +}) => ( +
+ + + Enable firewall rules + + {enabled ? ( + + Show inactive rules + + ) : null} + + {enabled && defaultRules.length ? ( + +

Default firewall rules

+ {/* trick H3 margin sibling rule */} + + {defaultRules.map(rule => ( + + + + ))} + +
+ ) : null} + {enabled && tagRules.length && defaultRules.length ? ( + + ) : null} + {enabled && tagRules.length ? ( + +

Firewall rules from instance tags

+ {/* trick H3 margin sibling rule */} + + {tagRules.map(rule => ( + + + + ))} + +
+ ) : null} + {enabled && (tagRules.length || defaultRules.length) ? ( + + ) : null} + +); diff --git a/packages/my-joy-beta/src/containers/create-instance/__tests__/__snapshots__/networks.spec.js.snap b/packages/my-joy-beta/src/containers/create-instance/__tests__/__snapshots__/networks.spec.js.snap index 10ac3f8d..83261515 100644 --- a/packages/my-joy-beta/src/containers/create-instance/__tests__/__snapshots__/networks.spec.js.snap +++ b/packages/my-joy-beta/src/containers/create-instance/__tests__/__snapshots__/networks.spec.js.snap @@ -163,7 +163,6 @@ Array [ />
,
, -
, ] `; @@ -329,7 +328,6 @@ Array [ height="0.0625rem" />
, -
, ] `; @@ -754,16 +752,14 @@ Array [ pointer-events: none; } -
- -
, +, ] `; @@ -1226,7 +1222,6 @@ Array [
, -
, ] `; @@ -2746,16 +2741,14 @@ Array [ pointer-events: none; } -
- -
, +, ] `; @@ -3370,15 +3363,13 @@ Array [ border-color: rgb(216,216,216); } -
- -
, +, ] `; diff --git a/packages/my-joy-beta/src/containers/create-instance/firewall.js b/packages/my-joy-beta/src/containers/create-instance/firewall.js new file mode 100644 index 00000000..2c4e07a9 --- /dev/null +++ b/packages/my-joy-beta/src/containers/create-instance/firewall.js @@ -0,0 +1,142 @@ +import React, { Fragment } from 'react'; +import { compose, graphql } from 'react-apollo'; +import { Margin } from 'styled-components-spacing'; +import ReduxForm from 'declarative-redux-form'; +import { set } from 'react-redux-values'; +import { connect } from 'react-redux'; +import get from 'lodash.get'; +import find from 'lodash.find'; +import forceArray from 'force-array'; + +import Title from '@components/create-instance/title'; +import FirewallForm from '@components/create-instance/firewall'; +import ListFwRules from '@graphql/list-fw-rules.gql'; + +import { StatusLoader, FirewallIcon, P, H3, Button } from 'joyent-ui-toolkit'; + +const FORM_NAME = 'CREATE-INSTANCE-FIREWALL'; + +const Firewall = ({ + defaultRules = [], + tagRules = [], + expanded = false, + proceeded = false, + loading = false, + enabled = false, + handleNext, + handleEdit +}) => ( + + }>Firewall + {expanded ? ( + +

+ Cloud Firewall rules control traffic across instances. Enabling the + firewall adds a default set of rules and rules defined by your chosen + tags.{' '} + + Read more + +

+
+ ) : null} + {loading && expanded ? : null} + {!loading ? ( + + {props => + expanded ? ( + + ) : null + } + + ) : null} + {proceeded && !expanded ? ( + +

{enabled ? 'Firewall Enabled' : 'Firewall Not Enabled'}

+
+ ) : null} + + {expanded ? ( + + ) : proceeded ? ( + + ) : null} + +
+); + +export default compose( + connect( + ({ form, values }, ownProps) => ({ + ...ownProps, + enabled: get(form, `${FORM_NAME}.values.enabled`, false), + showInactive: get(form, `${FORM_NAME}.values.show-inactive`, false), + tags: get(values, 'create-instance-tags', []) + }), + (dispatch, { history }) => ({ + handleNext: () => { + dispatch( + set({ name: 'create-instance-firewall-proceeded', value: true }) + ); + + return history.push('/instances/~create/cns'); + }, + handleEdit: () => { + return history.push('/instances/~create/firewall'); + } + }) + ), + graphql(ListFwRules, { + options: ({ tags, expanded, enabled }) => ({ + fetchPolicy: expanded && enabled ? 'cache-first' : 'cache-only', + variables: { + tags: tags.map(({ name, value }) => ({ name, value })) + } + }), + props: ({ ownProps, data }) => { + const { enabled, showInactive, tags = [] } = ownProps; + + const { + firewall_rules_create_machine = [], + loading, + error, + refetch + } = data; + + const rules = forceArray(firewall_rules_create_machine) + .filter(({ enabled }) => enabled || showInactive) + .map(({ rule_obj, ...rule }) => ({ + ...rule, + rule_obj: { + ...rule_obj, + from: forceArray(rule_obj.from).map(f => forceArray(f)), + to: forceArray(rule_obj.to).map(t => forceArray(t)) + } + })); + + return { + defaultRules: rules.filter(({ tag }) => !tag), + tagRules: rules.filter(({ tag }) => tag), + loading, + error, + refetch + }; + } + }) +)(Firewall); 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 57633c3f..f9b1e416 100644 --- a/packages/my-joy-beta/src/containers/create-instance/index.js +++ b/packages/my-joy-beta/src/containers/create-instance/index.js @@ -6,12 +6,13 @@ import { ViewContainer, H2, Button, Divider } from 'joyent-ui-toolkit'; import Name from '@containers/create-instance/name'; import Image from '@containers/create-instance/image'; -import Metadata from '@containers/create-instance/metadata'; -import Tags from '@containers/create-instance/tags'; import Package from '@containers/create-instance/package'; +import Tags from '@containers/create-instance/tags'; +import Metadata from '@containers/create-instance/metadata'; import Networks from '@containers/create-instance/networks'; -import Affinity from '@containers/create-instance/affinity'; +import Firewall from '@containers/create-instance/firewall'; import CNS from '@containers/create-instance/cns'; +import Affinity from '@containers/create-instance/affinity'; export default ({ step, ...props }) => ( @@ -36,6 +37,9 @@ export default ({ step, ...props }) => ( + + + diff --git a/packages/my-joy-beta/src/containers/create-instance/networks.js b/packages/my-joy-beta/src/containers/create-instance/networks.js index dcea73f9..e9f983a3 100644 --- a/packages/my-joy-beta/src/containers/create-instance/networks.js +++ b/packages/my-joy-beta/src/containers/create-instance/networks.js @@ -78,7 +78,7 @@ export const Networks = ({ )} ) : null} -
+ {expanded ? ( ) : null} -
+ ); }; @@ -130,7 +130,7 @@ export default compose( set({ name: 'create-instance-networks-proceeded', value: true }) ); - return history.push('/instances/~create/cns'); + return history.push('/instances/~create/firewall'); }, handleEdit: () => { return history.push('/instances/~create/networks'); diff --git a/packages/my-joy-beta/src/graphql/list-fw-rules.gql b/packages/my-joy-beta/src/graphql/list-fw-rules.gql new file mode 100644 index 00000000..c76eba50 --- /dev/null +++ b/packages/my-joy-beta/src/graphql/list-fw-rules.gql @@ -0,0 +1,10 @@ +query rules($tags: [KeyValueInput]!) { + firewall_rules_create_machine(tags: $tags) { + id + enabled + rule_obj + rule_str + global + tag + } +}