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
+}) => (
+
+);
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;
}
-
-
- Next
-
-
,
+
+ Next
+ ,
]
`;
@@ -1226,7 +1222,6 @@ Array [
,
-
,
]
`;
@@ -2746,16 +2741,14 @@ Array [
pointer-events: none;
}
-
-
- Next
-
-
,
+
+ Next
+ ,
]
`;
@@ -3370,15 +3363,13 @@ Array [
border-color: rgb(216,216,216);
}
-
-
- Edit
-
-
,
+
+ Edit
+ ,
]
`;
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 ? (
+
+ Next
+
+ ) : proceeded ? (
+
+ Edit
+
+ ) : 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 ? (
Next
@@ -88,7 +88,7 @@ export const Networks = ({
Edit
) : 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
+ }
+}