parent
069e56f921
commit
54d4b61250
@ -782,6 +782,7 @@ exports[`renders <Hostname values /> without throwing 1`] = `
|
|||||||
Instance name
|
Instance name
|
||||||
|
|
||||||
hostname
|
hostname
|
||||||
|
s
|
||||||
</small>
|
</small>
|
||||||
<div
|
<div
|
||||||
className="c4"
|
className="c4"
|
||||||
|
@ -75,7 +75,7 @@ export const Hostname = ({ values, network, service, ...hostname }) => (
|
|||||||
: network
|
: network
|
||||||
? 'Network'
|
? 'Network'
|
||||||
: service ? 'CNS service' : 'Instance name'}{' '}
|
: service ? 'CNS service' : 'Instance name'}{' '}
|
||||||
hostname
|
hostname{values.length === 1 ? '' : 's'}
|
||||||
</SmallBordered>
|
</SmallBordered>
|
||||||
<FlexItem>
|
<FlexItem>
|
||||||
<Margin right={1}>
|
<Margin right={1}>
|
||||||
|
161
packages/my-joy-beta/src/components/create-instance/firewall.js
Normal file
161
packages/my-joy-beta/src/components/create-instance/firewall.js
Normal file
@ -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 <span key={index}>{Wildcards[p[1]]}</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 <Tag key={index} name={name} value={value} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (
|
||||||
|
<Box disabled={!enabled}>
|
||||||
|
<Padding left={3} right={3} top={2} bottom={2}>
|
||||||
|
<Row>
|
||||||
|
<Col xs={3}>
|
||||||
|
<Flex justifyStart alignCenter contentStretch>
|
||||||
|
<FlexItem>
|
||||||
|
<b>From:{' '}</b>
|
||||||
|
</FlexItem>
|
||||||
|
<FlexItem grow={1}><TagList>{froms}</TagList></FlexItem>
|
||||||
|
</Flex>
|
||||||
|
</Col>
|
||||||
|
<Col xs={3}>
|
||||||
|
<Flex justifyStart alignCenter contentStretch>
|
||||||
|
<FlexItem>
|
||||||
|
<b>To:{' '}</b>
|
||||||
|
</FlexItem>
|
||||||
|
<FlexItem grow={1}><TagList>{tos}</TagList></FlexItem>
|
||||||
|
</Flex>
|
||||||
|
</Col>
|
||||||
|
<Col xs={2}>
|
||||||
|
<Flex justifyStart alignCenter contentStretch>
|
||||||
|
<FlexItem>
|
||||||
|
<b>Protocol:{' '}</b>
|
||||||
|
</FlexItem>
|
||||||
|
<FlexItem grow={1}>{protocol.name}</FlexItem>
|
||||||
|
</Flex>
|
||||||
|
</Col>
|
||||||
|
<Col xs={2}>
|
||||||
|
<Flex justifyStart alignCenter contentStretch>
|
||||||
|
<FlexItem>
|
||||||
|
<b>Ports:{' '}</b>
|
||||||
|
</FlexItem>
|
||||||
|
<FlexItem grow={1}>{protocol.targets.join(';')}</FlexItem>
|
||||||
|
</Flex>
|
||||||
|
</Col>
|
||||||
|
<Col xs={2}>
|
||||||
|
<Flex justifyStart alignCenter contentStretch>
|
||||||
|
<FlexItem>
|
||||||
|
<b>Action:{' '}</b>
|
||||||
|
</FlexItem>
|
||||||
|
<FlexItem grow={1}>{constantCase(action)}</FlexItem>
|
||||||
|
</Flex>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Padding>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ({
|
||||||
|
defaultRules = [],
|
||||||
|
tagRules = [],
|
||||||
|
enabled = false,
|
||||||
|
handleSubmit
|
||||||
|
}) => (
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<Margin bottom={4}>
|
||||||
|
<FormGroup name="enabled" field={Field}>
|
||||||
|
<Toggle>Enable firewall rules</Toggle>
|
||||||
|
</FormGroup>
|
||||||
|
{enabled ? (
|
||||||
|
<FormGroup name="show-inactive" field={Field}>
|
||||||
|
<Toggle>Show inactive rules</Toggle>
|
||||||
|
</FormGroup>
|
||||||
|
) : null}
|
||||||
|
</Margin>
|
||||||
|
{enabled && defaultRules.length ? (
|
||||||
|
<Fragment>
|
||||||
|
<H3>Default firewall rules</H3>
|
||||||
|
<span /> {/* trick H3 margin sibling rule */}
|
||||||
|
<Margin top={3}>
|
||||||
|
{defaultRules.map(rule => (
|
||||||
|
<Margin bottom={2}>
|
||||||
|
<Rule key={rule.id} {...rule} />
|
||||||
|
</Margin>
|
||||||
|
))}
|
||||||
|
</Margin>
|
||||||
|
</Fragment>
|
||||||
|
) : null}
|
||||||
|
{enabled && tagRules.length && defaultRules.length ? (
|
||||||
|
<Divider height={remcalc(18)} transparent />
|
||||||
|
) : null}
|
||||||
|
{enabled && tagRules.length ? (
|
||||||
|
<Fragment>
|
||||||
|
<H3>Firewall rules from instance tags</H3>
|
||||||
|
<span /> {/* trick H3 margin sibling rule */}
|
||||||
|
<Margin top={3}>
|
||||||
|
{tagRules.map(rule => (
|
||||||
|
<Margin bottom={2}>
|
||||||
|
<Rule key={rule.id} {...rule} />
|
||||||
|
</Margin>
|
||||||
|
))}
|
||||||
|
</Margin>
|
||||||
|
</Fragment>
|
||||||
|
) : null}
|
||||||
|
{enabled && (tagRules.length || defaultRules.length) ? (
|
||||||
|
<Divider height={remcalc(12)} transparent />
|
||||||
|
) : null}
|
||||||
|
</form>
|
||||||
|
);
|
@ -163,7 +163,6 @@ Array [
|
|||||||
/>
|
/>
|
||||||
</div>,
|
</div>,
|
||||||
<form />,
|
<form />,
|
||||||
<div />,
|
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -329,7 +328,6 @@ Array [
|
|||||||
height="0.0625rem"
|
height="0.0625rem"
|
||||||
/>
|
/>
|
||||||
</div>,
|
</div>,
|
||||||
<div />,
|
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -754,16 +752,14 @@ Array [
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
<div>
|
<button
|
||||||
<button
|
className="c0 c1 c2"
|
||||||
className="c0 c1 c2"
|
href=""
|
||||||
href=""
|
onClick={undefined}
|
||||||
onClick={undefined}
|
type="button"
|
||||||
type="button"
|
>
|
||||||
>
|
Next
|
||||||
Next
|
</button>,
|
||||||
</button>
|
|
||||||
</div>,
|
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -1226,7 +1222,6 @@ Array [
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>,
|
</form>,
|
||||||
<div />,
|
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -2746,16 +2741,14 @@ Array [
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
<div>
|
<button
|
||||||
<button
|
className="c0 c1 c2"
|
||||||
className="c0 c1 c2"
|
href=""
|
||||||
href=""
|
onClick={undefined}
|
||||||
onClick={undefined}
|
type="button"
|
||||||
type="button"
|
>
|
||||||
>
|
Next
|
||||||
Next
|
</button>,
|
||||||
</button>
|
|
||||||
</div>,
|
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -3370,15 +3363,13 @@ Array [
|
|||||||
border-color: rgb(216,216,216);
|
border-color: rgb(216,216,216);
|
||||||
}
|
}
|
||||||
|
|
||||||
<div>
|
<button
|
||||||
<button
|
className="c0 c1 c2"
|
||||||
className="c0 c1 c2"
|
href=""
|
||||||
href=""
|
onClick={undefined}
|
||||||
onClick={undefined}
|
type="button"
|
||||||
type="button"
|
>
|
||||||
>
|
Edit
|
||||||
Edit
|
</button>,
|
||||||
</button>
|
|
||||||
</div>,
|
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
142
packages/my-joy-beta/src/containers/create-instance/firewall.js
Normal file
142
packages/my-joy-beta/src/containers/create-instance/firewall.js
Normal file
@ -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
|
||||||
|
}) => (
|
||||||
|
<Fragment>
|
||||||
|
<Title icon={<FirewallIcon />}>Firewall</Title>
|
||||||
|
{expanded ? (
|
||||||
|
<Margin bottom={3}>
|
||||||
|
<P>
|
||||||
|
Cloud Firewall rules control traffic across instances. Enabling the
|
||||||
|
firewall adds a default set of rules and rules defined by your chosen
|
||||||
|
tags.{' '}
|
||||||
|
<a
|
||||||
|
target="__blank"
|
||||||
|
href="https://docs.joyent.com/public-cloud/network/firewall"
|
||||||
|
>
|
||||||
|
Read more
|
||||||
|
</a>
|
||||||
|
</P>
|
||||||
|
</Margin>
|
||||||
|
) : null}
|
||||||
|
{loading && expanded ? <StatusLoader /> : null}
|
||||||
|
{!loading ? (
|
||||||
|
<ReduxForm
|
||||||
|
form={FORM_NAME}
|
||||||
|
destroyOnUnmount={false}
|
||||||
|
forceUnregisterOnUnmount={true}
|
||||||
|
>
|
||||||
|
{props =>
|
||||||
|
expanded ? (
|
||||||
|
<FirewallForm
|
||||||
|
{...props}
|
||||||
|
defaultRules={defaultRules}
|
||||||
|
tagRules={tagRules}
|
||||||
|
enabled={enabled}
|
||||||
|
/>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
</ReduxForm>
|
||||||
|
) : null}
|
||||||
|
{proceeded && !expanded ? (
|
||||||
|
<Margin bottom={4}>
|
||||||
|
<H3>{enabled ? 'Firewall Enabled' : 'Firewall Not Enabled'}</H3>
|
||||||
|
</Margin>
|
||||||
|
) : null}
|
||||||
|
<Fragment>
|
||||||
|
{expanded ? (
|
||||||
|
<Button type="button" onClick={handleNext}>
|
||||||
|
Next
|
||||||
|
</Button>
|
||||||
|
) : proceeded ? (
|
||||||
|
<Button type="button" onClick={handleEdit} secondary>
|
||||||
|
Edit
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
</Fragment>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
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);
|
@ -6,12 +6,13 @@ import { ViewContainer, H2, Button, Divider } from 'joyent-ui-toolkit';
|
|||||||
|
|
||||||
import Name from '@containers/create-instance/name';
|
import Name from '@containers/create-instance/name';
|
||||||
import Image from '@containers/create-instance/image';
|
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 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 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 CNS from '@containers/create-instance/cns';
|
||||||
|
import Affinity from '@containers/create-instance/affinity';
|
||||||
|
|
||||||
export default ({ step, ...props }) => (
|
export default ({ step, ...props }) => (
|
||||||
<ViewContainer>
|
<ViewContainer>
|
||||||
@ -36,6 +37,9 @@ export default ({ step, ...props }) => (
|
|||||||
<Margin bottom={4}>
|
<Margin bottom={4}>
|
||||||
<Networks {...props} expanded={step === 'networks'} />
|
<Networks {...props} expanded={step === 'networks'} />
|
||||||
</Margin>
|
</Margin>
|
||||||
|
<Margin bottom={5}>
|
||||||
|
<Firewall {...props} expanded={step === 'firewall'} />
|
||||||
|
</Margin>
|
||||||
<Margin bottom={4}>
|
<Margin bottom={4}>
|
||||||
<CNS {...props} expanded={step === 'cns'} />
|
<CNS {...props} expanded={step === 'cns'} />
|
||||||
</Margin>
|
</Margin>
|
||||||
|
@ -78,7 +78,7 @@ export const Networks = ({
|
|||||||
)}
|
)}
|
||||||
</ReduxForm>
|
</ReduxForm>
|
||||||
) : null}
|
) : null}
|
||||||
<div>
|
<Fragment>
|
||||||
{expanded ? (
|
{expanded ? (
|
||||||
<Button type="button" onClick={handleNext}>
|
<Button type="button" onClick={handleNext}>
|
||||||
Next
|
Next
|
||||||
@ -88,7 +88,7 @@ export const Networks = ({
|
|||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</Fragment>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -130,7 +130,7 @@ export default compose(
|
|||||||
set({ name: 'create-instance-networks-proceeded', value: true })
|
set({ name: 'create-instance-networks-proceeded', value: true })
|
||||||
);
|
);
|
||||||
|
|
||||||
return history.push('/instances/~create/cns');
|
return history.push('/instances/~create/firewall');
|
||||||
},
|
},
|
||||||
handleEdit: () => {
|
handleEdit: () => {
|
||||||
return history.push('/instances/~create/networks');
|
return history.push('/instances/~create/networks');
|
||||||
|
10
packages/my-joy-beta/src/graphql/list-fw-rules.gql
Normal file
10
packages/my-joy-beta/src/graphql/list-fw-rules.gql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
query rules($tags: [KeyValueInput]!) {
|
||||||
|
firewall_rules_create_machine(tags: $tags) {
|
||||||
|
id
|
||||||
|
enabled
|
||||||
|
rule_obj
|
||||||
|
rule_str
|
||||||
|
global
|
||||||
|
tag
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user