import existing deployment groups (#516)
* refactor: config() from mutation to query * refactor(cp-frontend): remove unused dependency * feat(portal-watch): expose getContainers() and compose tags * fix(portal-watch): assert services by name AND hash * feat(portal-data): expose importable and import APIs * fix(portal-data): add missing dependencies * feat(portal-api): expose import/importable * feat(cp-gql-schema): add import/importable * feat(cp-frontend): import existing project * style(portal-watch): lint * style(portal-data): lint * chore: update lockfile
This commit is contained in:
parent
59043760b6
commit
7f1d731dc6
@ -5,6 +5,7 @@
|
|||||||
"new-cap": 0,
|
"new-cap": 0,
|
||||||
// temp
|
// temp
|
||||||
"no-undef": 1,
|
"no-undef": 1,
|
||||||
"no-debugger": 1
|
"no-debugger": 1,
|
||||||
|
"no-negated-condition": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
"unitcalc": "^1.0.8"
|
"unitcalc": "^1.0.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"apr-find": "^1.0.5",
|
|
||||||
"apr-for-each": "^1.0.6",
|
"apr-for-each": "^1.0.6",
|
||||||
"apr-main": "^1.0.7",
|
"apr-main": "^1.0.7",
|
||||||
"babel-plugin-inline-react-svg": "^0.4.0",
|
"babel-plugin-inline-react-svg": "^0.4.0",
|
||||||
|
@ -14,6 +14,15 @@
|
|||||||
border: solid 1px #d8d8d8;
|
border: solid 1px #d8d8d8;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html, body, #root {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#root {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
const { readFile, writeFile, exists } = require('mz/fs');
|
const { readFile, writeFile, exists } = require('mz/fs');
|
||||||
const main = require('apr-main');
|
const main = require('apr-main');
|
||||||
const forEach = require('apr-for-each');
|
const forEach = require('apr-for-each');
|
||||||
const find = require('apr-find');
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const ROOT = path.join(__dirname, '../node_modules/react-scripts/config');
|
const ROOT = path.join(__dirname, '../node_modules/react-scripts/config');
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Article } from 'normalized-styled-components';
|
|
||||||
import { ThemeProvider, injectGlobal } from 'styled-components';
|
import { ThemeProvider, injectGlobal } from 'styled-components';
|
||||||
import { theme, global } from 'joyent-ui-toolkit';
|
import { theme, global } from 'joyent-ui-toolkit';
|
||||||
import { ApolloProvider } from 'react-apollo';
|
import { ApolloProvider } from 'react-apollo';
|
||||||
@ -19,9 +18,7 @@ class App extends Component {
|
|||||||
return (
|
return (
|
||||||
<ApolloProvider client={client} store={store}>
|
<ApolloProvider client={client} store={store}>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<Article>
|
|
||||||
{Router}
|
{Router}
|
||||||
</Article>
|
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</ApolloProvider>
|
</ApolloProvider>
|
||||||
);
|
);
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { Col, Row } from 'react-styled-flexboxgrid';
|
|
||||||
|
|
||||||
export default () =>
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}>
|
|
||||||
<p>you don't have any deployment groups</p>
|
|
||||||
</Col>
|
|
||||||
</Row>;
|
|
@ -1 +1,2 @@
|
|||||||
export { default as EmptyDeployementGroups } from './empty';
|
export { default as DeploymentGroupsLoading } from './loading';
|
||||||
|
export { default as CreateDeploymentGroup } from './create';
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Col, Row } from 'react-styled-flexboxgrid';
|
||||||
|
import { Dots2 } from 'styled-text-spinners';
|
||||||
|
|
||||||
|
const LoadingRow = Row.extend`
|
||||||
|
flex: 1 1 auto;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default () =>
|
||||||
|
<LoadingRow center="xs" around="xs" middle="xs">
|
||||||
|
<Col xs={1}>
|
||||||
|
<Dots2 />
|
||||||
|
</Col>
|
||||||
|
</LoadingRow>;
|
@ -1,3 +1,13 @@
|
|||||||
import { Grid } from 'react-styled-flexboxgrid';
|
import { Grid } from 'react-styled-flexboxgrid';
|
||||||
|
import remcalc from 'remcalc';
|
||||||
|
import { isNot } from 'styled-is';
|
||||||
|
|
||||||
export default Grid;
|
export default Grid.extend`
|
||||||
|
padding-top: ${remcalc(19)};
|
||||||
|
|
||||||
|
${isNot('plain')`
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
`};
|
||||||
|
`;
|
||||||
|
@ -19,7 +19,6 @@ const BreadcrumbLink = styled(Link)`
|
|||||||
|
|
||||||
const BreadcrumbContainer = styled.div`
|
const BreadcrumbContainer = styled.div`
|
||||||
border-bottom: solid ${remcalc(1)} ${props => props.theme.grey};
|
border-bottom: solid ${remcalc(1)} ${props => props.theme.grey};
|
||||||
margin-bottom: ${remcalc(19)};
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const getBreadcrumbItems = (...links) =>
|
const getBreadcrumbItems = (...links) =>
|
||||||
|
@ -22,7 +22,7 @@ const getMenuItems = (...links) =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
const Menu = ({ links = [] }) =>
|
const Menu = ({ links = [] }) =>
|
||||||
<LayoutContainer>
|
<LayoutContainer plain>
|
||||||
<SectionList>
|
<SectionList>
|
||||||
{getMenuItems(...links)}
|
{getMenuItems(...links)}
|
||||||
</SectionList>
|
</SectionList>
|
||||||
|
@ -8,7 +8,7 @@ import paramCase from 'param-case';
|
|||||||
import DeploymentGroupBySlug from '@graphql/DeploymentGroupBySlug.gql';
|
import DeploymentGroupBySlug from '@graphql/DeploymentGroupBySlug.gql';
|
||||||
import DeploymentGroupCreateMutation from '@graphql/DeploymentGroupCreate.gql';
|
import DeploymentGroupCreateMutation from '@graphql/DeploymentGroupCreate.gql';
|
||||||
import DeploymentGroupProvisionMutation from '@graphql/DeploymentGroupProvision.gql';
|
import DeploymentGroupProvisionMutation from '@graphql/DeploymentGroupProvision.gql';
|
||||||
import DeploymentGroupConfigMutation from '@graphql/DeploymentGroupConfig.gql';
|
import DeploymentGroupConfigQuery from '@graphql/DeploymentGroupConfig.gql';
|
||||||
|
|
||||||
import { client } from '@state/store';
|
import { client } from '@state/store';
|
||||||
import { LayoutContainer } from '@components/layout';
|
import { LayoutContainer } from '@components/layout';
|
||||||
@ -262,7 +262,7 @@ export default compose(
|
|||||||
provisionManifest: variables => mutate({ variables })
|
provisionManifest: variables => mutate({ variables })
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
graphql(DeploymentGroupConfigMutation, {
|
graphql(DeploymentGroupConfigQuery, {
|
||||||
props: ({ mutate }) => ({
|
props: ({ mutate }) => ({
|
||||||
config: variables => mutate({ variables })
|
config: variables => mutate({ variables })
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { compose, graphql } from 'react-apollo';
|
||||||
|
import intercept from 'apr-intercept';
|
||||||
|
|
||||||
|
import DeploymentGroupImportMutation from '@graphql/DeploymentGroupImport.gql';
|
||||||
|
|
||||||
|
import { LayoutContainer } from '@components/layout';
|
||||||
|
import { DeploymentGroupsLoading } from '@components/deployment-groups';
|
||||||
|
import { Dots2 } from 'styled-text-spinners';
|
||||||
|
import { H2 } from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
|
class DeploymentGroupImport extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
loading: true,
|
||||||
|
error: false
|
||||||
|
};
|
||||||
|
|
||||||
|
setTimeout(this.importDeploymentGroup, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
importDeploymentGroup = async () => {
|
||||||
|
const { importDeploymentGroup, match, history } = this.props;
|
||||||
|
const { slug } = match.params;
|
||||||
|
|
||||||
|
const [error] = await intercept(
|
||||||
|
importDeploymentGroup({
|
||||||
|
slug
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return this.setState({ loading: false, error });
|
||||||
|
}
|
||||||
|
|
||||||
|
history.push(`/deployment-groups/${slug}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { loading, error } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LayoutContainer>
|
||||||
|
<H2>Importing deployment group</H2>
|
||||||
|
{loading && <DeploymentGroupsLoading />}
|
||||||
|
{error && <span>{error.toString()}</span>}
|
||||||
|
</LayoutContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default graphql(DeploymentGroupImportMutation, {
|
||||||
|
props: ({ mutate }) => ({
|
||||||
|
importDeploymentGroup: variables => mutate({ variables })
|
||||||
|
})
|
||||||
|
})(DeploymentGroupImport);
|
@ -1,2 +1,3 @@
|
|||||||
export { default as DeploymentGroupList } from './list';
|
export { default as DeploymentGroupList } from './list';
|
||||||
export { default as DeploymentGroupCreate } from './create';
|
export { default as DeploymentGroupCreate } from './create';
|
||||||
|
export { default as DeploymentGroupImport } from './import';
|
||||||
|
@ -1,73 +1,133 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { graphql } from 'react-apollo';
|
import { compose, graphql } from 'react-apollo';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import DeploymentGroupsQuery from '@graphql/DeploymentGroups.gql';
|
import styled from 'styled-components';
|
||||||
import { Col, Row } from 'react-styled-flexboxgrid';
|
import { Col, Row } from 'react-styled-flexboxgrid';
|
||||||
|
import forceArray from 'force-array';
|
||||||
|
import remcalc from 'remcalc';
|
||||||
|
|
||||||
import { LayoutContainer } from '@components/layout';
|
import { LayoutContainer } from '@components/layout';
|
||||||
import { Loader, ErrorMessage } from '@components/messaging';
|
import { Loader, ErrorMessage } from '@components/messaging';
|
||||||
import { EmptyDeployementGroups } from '@components/deployment-groups';
|
import { DeploymentGroupsLoading } from '@components/deployment-groups';
|
||||||
import { Button } from 'joyent-ui-toolkit';
|
import DeploymentGroupsQuery from '@graphql/DeploymentGroups.gql';
|
||||||
|
import DeploymentGroupsImportableQuery from '@graphql/DeploymentGroupsImportable.gql';
|
||||||
|
import { Button, H2, H3, Small } from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
|
const Title = H2.extend`
|
||||||
|
margin-top: ${remcalc(2)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const DGsRows = Row.extend`
|
||||||
|
margin-top: ${remcalc(-7)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Box = Col.withComponent(Link).extend`
|
||||||
|
text-decoration: none;
|
||||||
|
color: ${props => props.theme.secondary};
|
||||||
|
background-color: ${props => props.theme.white};
|
||||||
|
box-shadow: 0 ${remcalc(2)} 0 0 rgba(0, 0, 0, 0.05);
|
||||||
|
border: solid ${remcalc(1)} ${props => props.theme.grey};
|
||||||
|
margin-top: ${remcalc(20)};
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding: ${remcalc(18)};
|
||||||
|
min-height: ${remcalc(258)};
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: ${remcalc(20)};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const BoxCreate = Box.extend`
|
||||||
|
background-color: ${props => props.theme.disabled};
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
align-content: center;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: ${props => props.theme.white};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Oval = styled.div`
|
||||||
|
border: solid ${remcalc(1)} ${props => props.theme.grey};
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
width: ${remcalc(48)};
|
||||||
|
height: ${remcalc(48)};
|
||||||
|
line-height: ${remcalc(48)};
|
||||||
|
font-size: ${remcalc(24)};
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
margin-bottom: ${remcalc(20)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CreateTitle = Small.extend`
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ServiceTitle = H3.extend`
|
||||||
|
margin-top: ${remcalc(10)};
|
||||||
|
font-weight: 600;
|
||||||
|
`;
|
||||||
|
|
||||||
const DeploymentGroupList = ({
|
const DeploymentGroupList = ({
|
||||||
location,
|
location,
|
||||||
deploymentGroups,
|
deploymentGroups,
|
||||||
|
importable,
|
||||||
loading,
|
loading,
|
||||||
error
|
error,
|
||||||
|
match
|
||||||
}) => {
|
}) => {
|
||||||
if (loading) {
|
const _loading = !loading ? null : <DeploymentGroupsLoading />;
|
||||||
return (
|
|
||||||
<LayoutContainer>
|
// todo improve this error message style according to new designs
|
||||||
<Loader />
|
const _error = !error
|
||||||
</LayoutContainer>
|
? null
|
||||||
);
|
: <Row>
|
||||||
} else if (error) {
|
|
||||||
return (
|
|
||||||
<LayoutContainer>
|
|
||||||
<ErrorMessage message="Oops, and error occured while loading your deployment groups." />
|
<ErrorMessage message="Oops, and error occured while loading your deployment groups." />
|
||||||
</LayoutContainer>
|
</Row>;
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let emptyDeployementGroups = null;
|
const groups = forceArray(deploymentGroups).map(({ slug, name }) =>
|
||||||
let deploymentGroupList = null;
|
<Col xs={12} sm={4} md={3} lg={3} key={slug}>
|
||||||
|
<Box to={`${match.path}/${slug}`}>
|
||||||
if (deploymentGroups.length) {
|
<ServiceTitle>{name}</ServiceTitle>
|
||||||
const list = deploymentGroups.map((deploymentGroup, index) => {
|
</Box>
|
||||||
return (
|
|
||||||
<p key={index}>
|
|
||||||
<Link to={`${location.pathname}/${deploymentGroup.slug}/services`}>
|
|
||||||
{deploymentGroup.name}
|
|
||||||
</Link>
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
deploymentGroupList = (
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<ul>
|
|
||||||
{list}
|
|
||||||
</ul>
|
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
emptyDeployementGroups = <EmptyDeployementGroups />;
|
const create = [
|
||||||
}
|
<Col xs={12} sm={4} md={3} lg={3} key="~create">
|
||||||
|
<BoxCreate to={`${match.path}/~create`}>
|
||||||
|
<Oval>+</Oval>
|
||||||
|
<CreateTitle>Create new deployment group</CreateTitle>
|
||||||
|
</BoxCreate>
|
||||||
|
</Col>
|
||||||
|
].concat(
|
||||||
|
forceArray(importable).map(({ slug, name }) =>
|
||||||
|
<Col xs={12} sm={4} md={3} lg={3} key={slug}>
|
||||||
|
<BoxCreate to={`${match.path}/~import/${slug}`}>
|
||||||
|
<Oval>⤵</Oval>
|
||||||
|
<CreateTitle>{name}</CreateTitle>
|
||||||
|
</BoxCreate>
|
||||||
|
</Col>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LayoutContainer>
|
<LayoutContainer>
|
||||||
{emptyDeployementGroups}
|
<Title>Deployment groups</Title>
|
||||||
<Row>
|
{_loading}
|
||||||
<Col xs={12}>
|
{_error}
|
||||||
<Button to={`/deployment-groups/~create`}>
|
<DGsRows>
|
||||||
Create new
|
{groups}
|
||||||
</Button>
|
{create}
|
||||||
</Col>
|
</DGsRows>
|
||||||
</Row>
|
|
||||||
{deploymentGroupList}
|
|
||||||
</LayoutContainer>
|
</LayoutContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -81,7 +141,8 @@ DeploymentGroupList.propTypes = {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
const DeploymentGroupListWithData = graphql(DeploymentGroupsQuery, {
|
export default compose(
|
||||||
|
graphql(DeploymentGroupsQuery, {
|
||||||
options: {
|
options: {
|
||||||
pollInterval: 1000
|
pollInterval: 1000
|
||||||
},
|
},
|
||||||
@ -90,6 +151,10 @@ const DeploymentGroupListWithData = graphql(DeploymentGroupsQuery, {
|
|||||||
loading,
|
loading,
|
||||||
error
|
error
|
||||||
})
|
})
|
||||||
})(DeploymentGroupList);
|
}),
|
||||||
|
graphql(DeploymentGroupsImportableQuery, {
|
||||||
export default DeploymentGroupListWithData;
|
props: ({ data: { importableDeploymentGroups } }) => ({
|
||||||
|
importable: importableDeploymentGroups
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)(DeploymentGroupList);
|
||||||
|
@ -65,7 +65,7 @@ const ServicesMenu = ({ location, history: { push } }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LayoutContainer>
|
<LayoutContainer plain>
|
||||||
<H2>Services</H2>
|
<H2>Services</H2>
|
||||||
<PaddedRow>
|
<PaddedRow>
|
||||||
<Col xs={5}>
|
<Col xs={5}>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#import "./ServiceInfo.gql"
|
#import "./ServiceInfo.gql"
|
||||||
|
|
||||||
mutation config($deploymentGroupName: String!, $type: ManifestType!, $format: ManifestFormat!, $raw: String!) {
|
query config($deploymentGroupName: String!, $type: ManifestType!, $format: ManifestFormat!, $raw: String!) {
|
||||||
config(deploymentGroupName: $deploymentGroupName, type: $type, format: $format, raw: $raw) {
|
config(deploymentGroupName: $deploymentGroupName, type: $type, format: $format, raw: $raw) {
|
||||||
image
|
image
|
||||||
...ServiceInfo
|
...ServiceInfo
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
#import "./DeploymentGroupInfo.gql"
|
||||||
|
|
||||||
|
mutation importDeploymentGroup($slug: String!) {
|
||||||
|
importDeploymentGroup(deploymentGroupSlug: $slug) {
|
||||||
|
...DeploymentGroupInfo
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
#import "./DeploymentGroupInfo.gql"
|
||||||
|
|
||||||
|
query DeploymentGroupsImportable {
|
||||||
|
importableDeploymentGroups {
|
||||||
|
...DeploymentGroupInfo
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom';
|
import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import { Header, Breadcrumb, Menu } from '@containers/navigation';
|
import { Header, Breadcrumb, Menu } from '@containers/navigation';
|
||||||
|
import { ServiceScale, ServiceDelete } from '@containers/service';
|
||||||
|
import { InstanceList } from '@containers/instances';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DeploymentGroupList,
|
DeploymentGroupList,
|
||||||
DeploymentGroupCreate
|
DeploymentGroupCreate,
|
||||||
|
DeploymentGroupImport
|
||||||
} from '@containers/deployment-groups';
|
} from '@containers/deployment-groups';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -14,9 +18,12 @@ import {
|
|||||||
ServicesMenu
|
ServicesMenu
|
||||||
} from '@containers/services';
|
} from '@containers/services';
|
||||||
|
|
||||||
import { ServiceScale, ServiceDelete } from '@containers/service';
|
const Container = styled.div`
|
||||||
|
display: flex;
|
||||||
import { InstanceList } from '@containers/instances';
|
flex: 1 1 auto;
|
||||||
|
position: relative;
|
||||||
|
flex-flow: column;
|
||||||
|
`;
|
||||||
|
|
||||||
const rootRedirect = p => <Redirect to="/deployment-groups" />;
|
const rootRedirect = p => <Redirect to="/deployment-groups" />;
|
||||||
|
|
||||||
@ -33,7 +40,7 @@ const serviceRedirect = p =>
|
|||||||
|
|
||||||
const Router = (
|
const Router = (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<div style={{ position: 'relative' }}>
|
<Container>
|
||||||
|
|
||||||
<Route path="/" component={Header} />
|
<Route path="/" component={Header} />
|
||||||
|
|
||||||
@ -65,6 +72,11 @@ const Router = (
|
|||||||
exact
|
exact
|
||||||
component={DeploymentGroupCreate}
|
component={DeploymentGroupCreate}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path="/deployment-groups/~import/:slug"
|
||||||
|
exact
|
||||||
|
component={DeploymentGroupImport}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/deployment-groups/:deploymentGroup"
|
path="/deployment-groups/:deploymentGroup"
|
||||||
exact
|
exact
|
||||||
@ -132,7 +144,7 @@ const Router = (
|
|||||||
component={InstanceList}
|
component={InstanceList}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</Container>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -186,6 +186,9 @@ type Query {
|
|||||||
instance(id: ID!): Instance
|
instance(id: ID!): Instance
|
||||||
datacenter(id: ID, region: String): Datacenter
|
datacenter(id: ID, region: String): Datacenter
|
||||||
datacenters: [Datacenter]
|
datacenters: [Datacenter]
|
||||||
|
|
||||||
|
config(deploymentGroupName: String!, type: ManifestType!, format: ManifestFormat!, raw: String!): [Service]
|
||||||
|
importableDeploymentGroups: [DeploymentGroup]
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
@ -194,7 +197,6 @@ type Mutation {
|
|||||||
|
|
||||||
provisionManifest(deploymentGroupId: ID!, type: ManifestType!, format: ManifestFormat!, raw: String!): Version
|
provisionManifest(deploymentGroupId: ID!, type: ManifestType!, format: ManifestFormat!, raw: String!): Version
|
||||||
scale(serviceId: ID!, replicas: Int!): Version
|
scale(serviceId: ID!, replicas: Int!): Version
|
||||||
config(deploymentGroupName: String!, type: ManifestType!, format: ManifestFormat!, raw: String!): [Service]
|
|
||||||
|
|
||||||
stopServices(ids: [ID]!): [Service]
|
stopServices(ids: [ID]!): [Service]
|
||||||
startServices(ids: [ID]!): [Service]
|
startServices(ids: [ID]!): [Service]
|
||||||
@ -205,5 +207,5 @@ type Mutation {
|
|||||||
startInstances(ids: [ID]!): [Instance]
|
startInstances(ids: [ID]!): [Instance]
|
||||||
restartInstances(ids: [ID]!): [Instance]
|
restartInstances(ids: [ID]!): [Instance]
|
||||||
|
|
||||||
# reprovision() ???
|
importDeploymentGroup(deploymentGroupSlug: String!): DeploymentGroup
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,16 @@ module.exports = function (server, options, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = new PortalData(options.data);
|
const data = new PortalData(options.data);
|
||||||
|
const watcher = new PortalWatch(Object.assign(options.watch, {
|
||||||
const watch = new PortalWatch(Object.assign(options.watch, {
|
|
||||||
data
|
data
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// watcher <-> watcher
|
||||||
|
// portal depends on watcher and vice-versa
|
||||||
|
// I'm sure there is a better way to organize this domains
|
||||||
|
// but this works for now
|
||||||
|
data.setWatcher(watcher);
|
||||||
|
|
||||||
data.on('error', (err) => {
|
data.on('error', (err) => {
|
||||||
server.log(['error'], err);
|
server.log(['error'], err);
|
||||||
});
|
});
|
||||||
@ -33,12 +38,10 @@ module.exports = function (server, options, next) {
|
|||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
server.bind(Object.assign(data, {
|
server.bind(data);
|
||||||
watch
|
|
||||||
}));
|
|
||||||
|
|
||||||
Piloted.on('refresh', internals.refresh(data));
|
Piloted.on('refresh', internals.refresh(data));
|
||||||
watch.poll();
|
watcher.poll();
|
||||||
|
|
||||||
server.register([
|
server.register([
|
||||||
{
|
{
|
||||||
|
@ -25,7 +25,9 @@ module.exports = (data) => {
|
|||||||
'metricData',
|
'metricData',
|
||||||
'package',
|
'package',
|
||||||
'datacenters',
|
'datacenters',
|
||||||
'instanceMetric'
|
'instanceMetric',
|
||||||
|
'config',
|
||||||
|
'importableDeploymentGroups'
|
||||||
];
|
];
|
||||||
|
|
||||||
const mutations = [
|
const mutations = [
|
||||||
@ -33,14 +35,14 @@ module.exports = (data) => {
|
|||||||
'updateDeploymentGroup',
|
'updateDeploymentGroup',
|
||||||
'provisionManifest',
|
'provisionManifest',
|
||||||
'scale',
|
'scale',
|
||||||
'config',
|
|
||||||
'stopServices',
|
'stopServices',
|
||||||
'startServices',
|
'startServices',
|
||||||
'restartServices',
|
'restartServices',
|
||||||
'deleteServices',
|
'deleteServices',
|
||||||
'stopInstances',
|
'stopInstances',
|
||||||
'startInstances',
|
'startInstances',
|
||||||
'restartInstances'
|
'restartInstances',
|
||||||
|
'importDeploymentGroup'
|
||||||
];
|
];
|
||||||
|
|
||||||
const resolvers = {};
|
const resolvers = {};
|
||||||
|
@ -3,12 +3,23 @@
|
|||||||
const ParamCase = require('param-case');
|
const ParamCase = require('param-case');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const DockerClient = require('docker-compose-client');
|
const DockerClient = require('docker-compose-client');
|
||||||
|
const { DEPLOYMENT_GROUP, SERVICE, HASH } = require('portal-watch');
|
||||||
const Dockerode = require('dockerode');
|
const Dockerode = require('dockerode');
|
||||||
const Hoek = require('hoek');
|
const Hoek = require('hoek');
|
||||||
const Penseur = require('penseur');
|
const Penseur = require('penseur');
|
||||||
const VAsync = require('vasync');
|
const VAsync = require('vasync');
|
||||||
|
const uniqBy = require('lodash.uniqby');
|
||||||
const Transform = require('./transform');
|
const Transform = require('./transform');
|
||||||
const Uuid = require('uuid/v4');
|
const Uuid = require('uuid/v4');
|
||||||
|
const Util = require('util');
|
||||||
|
|
||||||
|
|
||||||
|
const NON_IMPORTABLE_STATES = [
|
||||||
|
'EXITED',
|
||||||
|
'DELETED',
|
||||||
|
'STOPPED',
|
||||||
|
'FAILED'
|
||||||
|
];
|
||||||
|
|
||||||
const internals = {
|
const internals = {
|
||||||
defaults: {
|
defaults: {
|
||||||
@ -51,12 +62,17 @@ module.exports = class Data extends EventEmitter {
|
|||||||
this._db = new Penseur.Db(settings.name, settings.db);
|
this._db = new Penseur.Db(settings.name, settings.db);
|
||||||
this._dockerCompose = new DockerClient(settings.dockerComposeHost);
|
this._dockerCompose = new DockerClient(settings.dockerComposeHost);
|
||||||
this._docker = new Dockerode(settings.docker);
|
this._docker = new Dockerode(settings.docker);
|
||||||
|
this._watcher = null;
|
||||||
|
|
||||||
this._dockerCompose.on('error', (err) => {
|
this._dockerCompose.on('error', (err) => {
|
||||||
this.emit('error', err);
|
this.emit('error', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setWatcher (watcher) {
|
||||||
|
this._watcher = watcher;
|
||||||
|
}
|
||||||
|
|
||||||
connect (cb) {
|
connect (cb) {
|
||||||
this._db.establish(internals.tables, cb);
|
this._db.establish(internals.tables, cb);
|
||||||
}
|
}
|
||||||
@ -284,10 +300,8 @@ module.exports = class Data extends EventEmitter {
|
|||||||
const deploymentGroup = deploymentGroups[0];
|
const deploymentGroup = deploymentGroups[0];
|
||||||
|
|
||||||
const getServices = (args) => {
|
const getServices = (args) => {
|
||||||
console.log(args);
|
|
||||||
args = args || {};
|
args = args || {};
|
||||||
args.deploymentGroupId = deploymentGroup.id;
|
args.deploymentGroupId = deploymentGroup.id;
|
||||||
console.log(args);
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.getServices(args, resolveCb(resolve, reject));
|
this.getServices(args, resolveCb(resolve, reject));
|
||||||
@ -1285,7 +1299,7 @@ module.exports = class Data extends EventEmitter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
config ({deploymentGroupName = '', type = '', format = '', raw = '' }, cb) {
|
getConfig ({deploymentGroupName = '', type = '', format = '', raw = '' }, cb) {
|
||||||
if (type.toUpperCase() !== 'COMPOSE') {
|
if (type.toUpperCase() !== 'COMPOSE') {
|
||||||
return cb(new Error('"COMPOSE" is the only `type` supported'));
|
return cb(new Error('"COMPOSE" is the only `type` supported'));
|
||||||
}
|
}
|
||||||
@ -1330,4 +1344,133 @@ module.exports = class Data extends EventEmitter {
|
|||||||
}, []));
|
}, []));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getImportableDeploymentGroups (args, cb) {
|
||||||
|
if (!this._watcher) {
|
||||||
|
return cb(null, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
const machines = this._watcher.getContainers();
|
||||||
|
|
||||||
|
if (!Array.isArray(machines)) {
|
||||||
|
return cb(null, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb(
|
||||||
|
null,
|
||||||
|
uniqBy(
|
||||||
|
machines
|
||||||
|
.filter(({ state }) => { return NON_IMPORTABLE_STATES.indexOf(state.toUpperCase()) < 0; })
|
||||||
|
.filter(({ tags = {} }) => { return [DEPLOYMENT_GROUP, SERVICE, HASH].every((name) => { return tags[name]; }); }
|
||||||
|
)
|
||||||
|
.map(({ tags = {} }) => {
|
||||||
|
return ({
|
||||||
|
id: Uuid(),
|
||||||
|
name: tags[DEPLOYMENT_GROUP],
|
||||||
|
slug: ParamCase(tags[DEPLOYMENT_GROUP])
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
'slug'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
importDeploymentGroup ({ deploymentGroupSlug }, cb) {
|
||||||
|
console.log(`-> import requested for ${deploymentGroupSlug}`);
|
||||||
|
|
||||||
|
if (!this._watcher) {
|
||||||
|
console.log('-> watcher not yet defined');
|
||||||
|
return cb(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const machines = this._watcher.getContainers();
|
||||||
|
|
||||||
|
if (!Array.isArray(machines)) {
|
||||||
|
console.log('-> no machines found');
|
||||||
|
return cb(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const containers = machines
|
||||||
|
.filter(
|
||||||
|
({ tags = {} }) => { return tags[DEPLOYMENT_GROUP] && ParamCase(tags[DEPLOYMENT_GROUP]) === deploymentGroupSlug; }
|
||||||
|
)
|
||||||
|
.filter(
|
||||||
|
({ state }) => { return NON_IMPORTABLE_STATES.indexOf(state.toUpperCase()) < 0; }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!containers.length) {
|
||||||
|
console.log(`-> no containers found for ${deploymentGroupSlug}`);
|
||||||
|
return cb(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { tags = [] } = containers[0];
|
||||||
|
|
||||||
|
const services = containers.reduce((acc, { tags = [], id = '', state = '', name = '' }) => {
|
||||||
|
const hash = tags[HASH];
|
||||||
|
const slug = ParamCase(tags[SERVICE]);
|
||||||
|
const attr = `${hash}-${slug}`;
|
||||||
|
|
||||||
|
const instance = {
|
||||||
|
name: name,
|
||||||
|
machineId: id,
|
||||||
|
status: state.toUpperCase()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (acc[attr]) {
|
||||||
|
acc[attr].instances.push(instance);
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.assign(acc, {
|
||||||
|
[attr]: {
|
||||||
|
hash,
|
||||||
|
name: tags[SERVICE],
|
||||||
|
slug,
|
||||||
|
instances: [instance]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const createService = (deploymentGroupId) => {
|
||||||
|
return (serviceId, next) => {
|
||||||
|
const service = services[serviceId];
|
||||||
|
|
||||||
|
console.log(`-> creating Service ${Util.inspect(service)}`);
|
||||||
|
|
||||||
|
VAsync.forEachParallel({
|
||||||
|
inputs: service.instances,
|
||||||
|
func: (instance, next) => { return this.createInstance(instance, next); }
|
||||||
|
}, (err, results) => {
|
||||||
|
if (err) {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`-> created Instances ${Util.inspect(results.successes)}`);
|
||||||
|
|
||||||
|
this.createService(Object.assign(service, {
|
||||||
|
instances: results.successes,
|
||||||
|
deploymentGroupId
|
||||||
|
}), next);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const deploymentGroup = {
|
||||||
|
name: tags[DEPLOYMENT_GROUP],
|
||||||
|
slug: ParamCase(tags[DEPLOYMENT_GROUP])
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log(`-> creating DeploymentGroup ${Util.inspect(deploymentGroup)}`);
|
||||||
|
|
||||||
|
this.createDeploymentGroup(deploymentGroup, (err, dg) => {
|
||||||
|
if (err) {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
VAsync.forEachParallel({
|
||||||
|
inputs: Object.keys(services),
|
||||||
|
func: createService(dg.id)
|
||||||
|
}, (err) => { return cb(err, dg); });
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
"hoek": "^4.1.1",
|
"hoek": "^4.1.1",
|
||||||
"param-case": "^2.1.1",
|
"param-case": "^2.1.1",
|
||||||
"penseur": "^7.12.3",
|
"penseur": "^7.12.3",
|
||||||
|
"lodash.uniqby": "^4.7.0",
|
||||||
|
"portal-watch": "^1.0.0",
|
||||||
"uuid": "^3.1.0",
|
"uuid": "^3.1.0",
|
||||||
"vasync": "^1.6.4",
|
"vasync": "^1.6.4",
|
||||||
"yamljs": "^0.2.10"
|
"yamljs": "^0.2.10"
|
||||||
|
@ -9,7 +9,6 @@ const DEPLOYMENT_GROUP = 'docker:label:com.docker.compose.project';
|
|||||||
const SERVICE = 'docker:label:com.docker.compose.service';
|
const SERVICE = 'docker:label:com.docker.compose.service';
|
||||||
const HASH = 'docker:label:com.docker.compose.config-hash';
|
const HASH = 'docker:label:com.docker.compose.config-hash';
|
||||||
|
|
||||||
|
|
||||||
module.exports = class Watcher {
|
module.exports = class Watcher {
|
||||||
constructor (options) {
|
constructor (options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
@ -35,6 +34,10 @@ module.exports = class Watcher {
|
|||||||
this._tritonWatch.poll();
|
this._tritonWatch.poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getContainers () {
|
||||||
|
return this._tritonWatch.getContainers();
|
||||||
|
}
|
||||||
|
|
||||||
getDeploymentGroupId (name, cb) {
|
getDeploymentGroupId (name, cb) {
|
||||||
this._data.getDeploymentGroup({ name }, (err, deploymentGroup) => {
|
this._data.getDeploymentGroup({ name }, (err, deploymentGroup) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -45,8 +48,8 @@ module.exports = class Watcher {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getService ({ serviceName, deploymentGroupId }, cb) {
|
getService ({ serviceName, serviceHash, deploymentGroupId }, cb) {
|
||||||
this._data.getServices({ name: serviceName, deploymentGroupId }, (err, services) => {
|
this._data.getServices({ name: serviceName, hash: serviceHash, deploymentGroupId }, (err, services) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return cb(err);
|
return cb(err);
|
||||||
}
|
}
|
||||||
@ -131,7 +134,7 @@ module.exports = class Watcher {
|
|||||||
|
|
||||||
console.log('-> `change` event received', util.inspect(machine));
|
console.log('-> `change` event received', util.inspect(machine));
|
||||||
|
|
||||||
const { id, tags = [] } = machine;
|
const { id, tags = {} } = machine;
|
||||||
|
|
||||||
// assert id existence
|
// assert id existence
|
||||||
if (!id) {
|
if (!id) {
|
||||||
@ -175,7 +178,7 @@ module.exports = class Watcher {
|
|||||||
|
|
||||||
// assert that service exists
|
// assert that service exists
|
||||||
const assertService = (deploymentGroupId) => {
|
const assertService = (deploymentGroupId) => {
|
||||||
this.getService({ serviceName, deploymentGroupId }, handleError((service) => {
|
this.getService({ serviceName, serviceHash: tags[HASH], deploymentGroupId }, handleError((service) => {
|
||||||
if (!service) {
|
if (!service) {
|
||||||
console.error(`Service "${serviceName}" form DeploymentGroup "${deploymentGroupName}" for machine ${id} not found`);
|
console.error(`Service "${serviceName}" form DeploymentGroup "${deploymentGroupName}" for machine ${id} not found`);
|
||||||
return;
|
return;
|
||||||
@ -200,3 +203,7 @@ module.exports = class Watcher {
|
|||||||
assertDeploymentGroup();
|
assertDeploymentGroup();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports.DEPLOYMENT_GROUP = DEPLOYMENT_GROUP;
|
||||||
|
module.exports.SERVICE = SERVICE;
|
||||||
|
module.exports.HASH = HASH;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
"test-ci": "echo 0 `# lab -c -r console -o stdout -r tap -o $CIRCLE_TEST_REPORTS/test/portal-watch.xml`"
|
"test-ci": "echo 0 `# lab -c -r console -o stdout -r tap -o $CIRCLE_TEST_REPORTS/test/portal-watch.xml`"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"triton-watch": "^1.0.1"
|
"triton-watch": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"belly-button": "^3.1.0",
|
"belly-button": "^3.1.0",
|
||||||
|
102
yarn.lock
102
yarn.lock
@ -42,8 +42,8 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.40.tgz#ac02de68e66c004a61b7cb16df8b1db3a254cca9"
|
resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.40.tgz#ac02de68e66c004a61b7cb16df8b1db3a254cca9"
|
||||||
|
|
||||||
"@types/graphql@^0.9.0":
|
"@types/graphql@^0.9.0":
|
||||||
version "0.9.1"
|
version "0.9.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.9.1.tgz#b04ebe84bc997cc60dbea2ed4d0d4342c737f99d"
|
resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.9.2.tgz#5e3a2919a998d0bd9bb86b4b23e9630425bff1b2"
|
||||||
|
|
||||||
"@types/isomorphic-fetch@0.0.34":
|
"@types/isomorphic-fetch@0.0.34":
|
||||||
version "0.0.34"
|
version "0.0.34"
|
||||||
@ -305,15 +305,6 @@ apr-filter@^1.0.5:
|
|||||||
apr-engine-sum "^1.0.3"
|
apr-engine-sum "^1.0.3"
|
||||||
apr-map "^1.0.5"
|
apr-map "^1.0.5"
|
||||||
|
|
||||||
apr-find@^1.0.5:
|
|
||||||
version "1.0.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/apr-find/-/apr-find-1.0.5.tgz#e166abc66f53cfd08aadb3ecab38049faa378301"
|
|
||||||
dependencies:
|
|
||||||
apr-engine-each "^1.0.3"
|
|
||||||
apr-engine-sum "^1.0.3"
|
|
||||||
lodash.defaults "^4.2.0"
|
|
||||||
lodash.isarraylike "^4.2.0"
|
|
||||||
|
|
||||||
apr-for-each@^1.0.6:
|
apr-for-each@^1.0.6:
|
||||||
version "1.0.6"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/apr-for-each/-/apr-for-each-1.0.6.tgz#3947bb25fdb7b79a7f02bfa925fdb79576098903"
|
resolved "https://registry.yarnpkg.com/apr-for-each/-/apr-for-each-1.0.6.tgz#3947bb25fdb7b79a7f02bfa925fdb79576098903"
|
||||||
@ -502,6 +493,10 @@ ast-types@0.9.0:
|
|||||||
version "0.9.0"
|
version "0.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.0.tgz#c8721c8747ae4d5b29b929e99c5317b4e8745623"
|
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.0.tgz#c8721c8747ae4d5b29b929e99c5317b4e8745623"
|
||||||
|
|
||||||
|
ast-types@0.9.6:
|
||||||
|
version "0.9.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
|
||||||
|
|
||||||
async-each@^1.0.0:
|
async-each@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
|
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
|
||||||
@ -511,8 +506,8 @@ async@^1.4.0, async@^1.5.0:
|
|||||||
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
|
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
|
||||||
|
|
||||||
async@^2.0.1, async@^2.1.2, async@^2.1.4:
|
async@^2.0.1, async@^2.1.2, async@^2.1.4:
|
||||||
version "2.4.1"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7"
|
resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d"
|
||||||
dependencies:
|
dependencies:
|
||||||
lodash "^4.14.0"
|
lodash "^4.14.0"
|
||||||
|
|
||||||
@ -896,10 +891,10 @@ babel-plugin-istanbul@^4.1.4:
|
|||||||
test-exclude "^4.1.1"
|
test-exclude "^4.1.1"
|
||||||
|
|
||||||
babel-plugin-styled-components@^1.1.4:
|
babel-plugin-styled-components@^1.1.4:
|
||||||
version "1.1.4"
|
version "1.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.1.4.tgz#b0e6d5bb01059bc7ab9118d3d686f6472ee8e91f"
|
resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.1.5.tgz#ff2c8e0e2f3a0d3279e7454a7aaa2973749e714d"
|
||||||
dependencies:
|
dependencies:
|
||||||
stylis "2.0.0"
|
stylis "^3.0.19"
|
||||||
|
|
||||||
babel-plugin-syntax-async-functions@^6.8.0:
|
babel-plugin-syntax-async-functions@^6.8.0:
|
||||||
version "6.13.0"
|
version "6.13.0"
|
||||||
@ -1370,7 +1365,7 @@ babelrc-rollup@3.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
resolve "^1.1.7"
|
resolve "^1.1.7"
|
||||||
|
|
||||||
babylon@^6.1.0, babylon@^6.10.0, babylon@^6.12.0, babylon@^6.13.0, babylon@^6.17.0, babylon@^6.17.2:
|
babylon@^6.1.0, babylon@^6.10.0, babylon@^6.12.0, babylon@^6.17.0, babylon@^6.17.2, babylon@^6.17.4:
|
||||||
version "6.17.4"
|
version "6.17.4"
|
||||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a"
|
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a"
|
||||||
|
|
||||||
@ -1766,12 +1761,12 @@ camelcase@^4.0.0, camelcase@^4.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
||||||
|
|
||||||
caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
||||||
version "1.0.30000693"
|
version "1.0.30000694"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000693.tgz#8510e7a9ab04adcca23a5dcefa34df9d28c1ce20"
|
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000694.tgz#02009f4f82d2f0126e4c691b7cd5adb351935c01"
|
||||||
|
|
||||||
caniuse-lite@^1.0.30000684:
|
caniuse-lite@^1.0.30000684:
|
||||||
version "1.0.30000693"
|
version "1.0.30000694"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000693.tgz#c9c6298697c71fdf6cb13eefe8aa93926f2f8613"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000694.tgz#1492dab7c10c608c9d37a723e6e3e7873e0ce94f"
|
||||||
|
|
||||||
capture-stack-trace@^1.0.0:
|
capture-stack-trace@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
@ -2027,8 +2022,8 @@ coleman-liau@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/coleman-liau/-/coleman-liau-1.0.0.tgz#de1f39901e164f49eff2a6ec88f3a9dbbb6686c1"
|
resolved "https://registry.yarnpkg.com/coleman-liau/-/coleman-liau-1.0.0.tgz#de1f39901e164f49eff2a6ec88f3a9dbbb6686c1"
|
||||||
|
|
||||||
collapse-white-space@^1.0.2:
|
collapse-white-space@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.2.tgz#9c463fb9c6d190d2dcae21a356a01bcae9eeef6d"
|
resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.3.tgz#4b906f670e5a963a87b76b0e1689643341b6023c"
|
||||||
|
|
||||||
color-convert@^1.0.0:
|
color-convert@^1.0.0:
|
||||||
version "1.9.0"
|
version "1.9.0"
|
||||||
@ -2081,8 +2076,8 @@ command-join@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/command-join/-/command-join-2.0.0.tgz#52e8b984f4872d952ff1bdc8b98397d27c7144cf"
|
resolved "https://registry.yarnpkg.com/command-join/-/command-join-2.0.0.tgz#52e8b984f4872d952ff1bdc8b98397d27c7144cf"
|
||||||
|
|
||||||
commander@2, commander@^2.7.1, commander@^2.8.1, commander@^2.9.0:
|
commander@2, commander@^2.7.1, commander@^2.8.1, commander@^2.9.0:
|
||||||
version "2.9.0"
|
version "2.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.10.0.tgz#e1f5d3245de246d1a5ca04702fa1ad1bd7e405fe"
|
||||||
dependencies:
|
dependencies:
|
||||||
graceful-readlink ">= 1.0.0"
|
graceful-readlink ">= 1.0.0"
|
||||||
|
|
||||||
@ -3352,8 +3347,8 @@ eslint-plugin-hapi@4.x.x:
|
|||||||
no-arrowception "1.x.x"
|
no-arrowception "1.x.x"
|
||||||
|
|
||||||
eslint-plugin-import@^2.3.0:
|
eslint-plugin-import@^2.3.0:
|
||||||
version "2.5.0"
|
version "2.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.5.0.tgz#293b5ea7910a901a05a47ccdd7546e611725406c"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.6.0.tgz#2a4bbad36a078e052a3c830ce3dfbd6b8a12c6e5"
|
||||||
dependencies:
|
dependencies:
|
||||||
builtin-modules "^1.1.1"
|
builtin-modules "^1.1.1"
|
||||||
contains-path "^0.1.0"
|
contains-path "^0.1.0"
|
||||||
@ -3498,7 +3493,7 @@ esprima@^2.6.0, esprima@~2.7.1:
|
|||||||
version "2.7.3"
|
version "2.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
|
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
|
||||||
|
|
||||||
esprima@^3.1.1:
|
esprima@^3.1.1, esprima@~3.1.0:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
|
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
|
||||||
|
|
||||||
@ -5009,14 +5004,14 @@ istanbul-lib-hook@^1.0.7:
|
|||||||
append-transform "^0.4.0"
|
append-transform "^0.4.0"
|
||||||
|
|
||||||
istanbul-lib-instrument@^1.7.2:
|
istanbul-lib-instrument@^1.7.2:
|
||||||
version "1.7.2"
|
version "1.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.2.tgz#6014b03d3470fb77638d5802508c255c06312e56"
|
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.3.tgz#925b239163eabdd68cc4048f52c2fa4f899ecfa7"
|
||||||
dependencies:
|
dependencies:
|
||||||
babel-generator "^6.18.0"
|
babel-generator "^6.18.0"
|
||||||
babel-template "^6.16.0"
|
babel-template "^6.16.0"
|
||||||
babel-traverse "^6.18.0"
|
babel-traverse "^6.18.0"
|
||||||
babel-types "^6.18.0"
|
babel-types "^6.18.0"
|
||||||
babylon "^6.13.0"
|
babylon "^6.17.4"
|
||||||
istanbul-lib-coverage "^1.1.1"
|
istanbul-lib-coverage "^1.1.1"
|
||||||
semver "^5.3.0"
|
semver "^5.3.0"
|
||||||
|
|
||||||
@ -5196,8 +5191,8 @@ jest-snapshot@^20.0.3:
|
|||||||
pretty-format "^20.0.3"
|
pretty-format "^20.0.3"
|
||||||
|
|
||||||
jest-styled-components@^3.0.2:
|
jest-styled-components@^3.0.2:
|
||||||
version "3.1.3"
|
version "3.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/jest-styled-components/-/jest-styled-components-3.1.3.tgz#eba50074b426e36fd2be99187dffa4b5569eab00"
|
resolved "https://registry.yarnpkg.com/jest-styled-components/-/jest-styled-components-3.1.5.tgz#c1e4fc60e534e54b26c3b733b65b44afd4f2795e"
|
||||||
dependencies:
|
dependencies:
|
||||||
css "^2.2.1"
|
css "^2.2.1"
|
||||||
|
|
||||||
@ -5460,8 +5455,8 @@ known-css-properties@^0.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.2.0.tgz#899c94be368e55b42d7db8d5be7d73a4a4a41454"
|
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.2.0.tgz#899c94be368e55b42d7db8d5be7d73a4a4a41454"
|
||||||
|
|
||||||
lab@^14.0.1:
|
lab@^14.0.1:
|
||||||
version "14.0.1"
|
version "14.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/lab/-/lab-14.0.1.tgz#1a20100ecc692dbf91e849cd6b945b8e016a0527"
|
resolved "https://registry.yarnpkg.com/lab/-/lab-14.1.0.tgz#2632b9a416d5f391d9a6f1d98d607b0d69f75629"
|
||||||
dependencies:
|
dependencies:
|
||||||
bossy "3.x.x"
|
bossy "3.x.x"
|
||||||
code "4.1.x"
|
code "4.1.x"
|
||||||
@ -5934,8 +5929,8 @@ matcher@^0.1.1:
|
|||||||
escape-string-regexp "^1.0.4"
|
escape-string-regexp "^1.0.4"
|
||||||
|
|
||||||
mathml-tag-names@^2.0.0:
|
mathml-tag-names@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.0.0.tgz#eee615112a2b127e70f558d69c9ebe14076503d7"
|
resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.0.1.tgz#8d41268168bf86d1102b98109e28e531e7a34578"
|
||||||
|
|
||||||
max-safe-int@^1.0.0:
|
max-safe-int@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
@ -6916,8 +6911,8 @@ podium@1.x.x:
|
|||||||
joi "10.x.x"
|
joi "10.x.x"
|
||||||
|
|
||||||
polished@^1.1.3:
|
polished@^1.1.3:
|
||||||
version "1.2.0"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/polished/-/polished-1.2.0.tgz#241cbbbd848d62ca8776eee618383d72e95830c5"
|
resolved "https://registry.yarnpkg.com/polished/-/polished-1.2.1.tgz#83c18a85bf9d7023477cfc7049763b657d50f0f7"
|
||||||
|
|
||||||
pos@0.4.2:
|
pos@0.4.2:
|
||||||
version "0.4.2"
|
version "0.4.2"
|
||||||
@ -7036,8 +7031,8 @@ pretty-ms@^2.0.0:
|
|||||||
plur "^1.0.0"
|
plur "^1.0.0"
|
||||||
|
|
||||||
primer-support@*:
|
primer-support@*:
|
||||||
version "4.0.0"
|
version "4.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/primer-support/-/primer-support-4.0.0.tgz#3dbbb37e4e0f2ed2ea6035e0b79dd0cb33bae85e"
|
resolved "https://registry.yarnpkg.com/primer-support/-/primer-support-4.0.4.tgz#7f16ad577a61a960d0bccd72f2a6df506a14d69f"
|
||||||
|
|
||||||
primer-utilities@^3.0.0:
|
primer-utilities@^3.0.0:
|
||||||
version "3.5.0"
|
version "3.5.0"
|
||||||
@ -7526,7 +7521,7 @@ readline2@^1.0.1:
|
|||||||
is-fullwidth-code-point "^1.0.0"
|
is-fullwidth-code-point "^1.0.0"
|
||||||
mute-stream "0.0.5"
|
mute-stream "0.0.5"
|
||||||
|
|
||||||
recast@0.11.12, recast@^0.11.5:
|
recast@0.11.12:
|
||||||
version "0.11.12"
|
version "0.11.12"
|
||||||
resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.12.tgz#a79e4d3f82d5d72a82ee177aeaa791e793bbe5d6"
|
resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.12.tgz#a79e4d3f82d5d72a82ee177aeaa791e793bbe5d6"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -7535,6 +7530,15 @@ recast@0.11.12, recast@^0.11.5:
|
|||||||
private "~0.1.5"
|
private "~0.1.5"
|
||||||
source-map "~0.5.0"
|
source-map "~0.5.0"
|
||||||
|
|
||||||
|
recast@^0.11.5:
|
||||||
|
version "0.11.23"
|
||||||
|
resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
|
||||||
|
dependencies:
|
||||||
|
ast-types "0.9.6"
|
||||||
|
esprima "~3.1.0"
|
||||||
|
private "~0.1.5"
|
||||||
|
source-map "~0.5.0"
|
||||||
|
|
||||||
rechoir@^0.6.2:
|
rechoir@^0.6.2:
|
||||||
version "0.6.2"
|
version "0.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
||||||
@ -8314,8 +8318,8 @@ spache@^1.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/spache/-/spache-1.1.0.tgz#8c68ba807630f0199429c2035c82ed96f5438cd5"
|
resolved "https://registry.yarnpkg.com/spache/-/spache-1.1.0.tgz#8c68ba807630f0199429c2035c82ed96f5438cd5"
|
||||||
|
|
||||||
spawn-wrap@^1.3.6:
|
spawn-wrap@^1.3.6:
|
||||||
version "1.3.6"
|
version "1.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.3.6.tgz#ccec4a949d8ce7e2b1a35cf4671d683d2e76a1d1"
|
resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.3.7.tgz#beb8bf4426d64b2b06871e0d7dee2643f1f8d1bc"
|
||||||
dependencies:
|
dependencies:
|
||||||
foreground-child "^1.5.6"
|
foreground-child "^1.5.6"
|
||||||
mkdirp "^0.5.0"
|
mkdirp "^0.5.0"
|
||||||
@ -8714,10 +8718,6 @@ stylelint@^7.0.0, stylelint@^7.0.3, stylelint@^7.11.1:
|
|||||||
svg-tags "^1.0.0"
|
svg-tags "^1.0.0"
|
||||||
table "^4.0.1"
|
table "^4.0.1"
|
||||||
|
|
||||||
stylis@2.0.0:
|
|
||||||
version "2.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-2.0.0.tgz#6785a6546bd73478799a67d49d67086953b50ad5"
|
|
||||||
|
|
||||||
stylis@^3.0.19:
|
stylis@^3.0.19:
|
||||||
version "3.1.9"
|
version "3.1.9"
|
||||||
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.1.9.tgz#638370451f980437f57c59e58d2e296be29fafb7"
|
resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.1.9.tgz#638370451f980437f57c59e58d2e296be29fafb7"
|
||||||
@ -9128,9 +9128,9 @@ trim@0.0.1:
|
|||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd"
|
resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd"
|
||||||
|
|
||||||
triton-watch@^1.0.1:
|
triton-watch@^1.1.0:
|
||||||
version "1.0.1"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/triton-watch/-/triton-watch-1.0.1.tgz#b1087f6a57383f1e83d0a308e65110ca9a2a38d0"
|
resolved "https://registry.yarnpkg.com/triton-watch/-/triton-watch-1.1.0.tgz#d2b47fbf6a45174198c196152bb86c696a923c35"
|
||||||
dependencies:
|
dependencies:
|
||||||
triton "5.2.x"
|
triton "5.2.x"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user