mirror of
https://github.com/yldio/copilot.git
synced 2024-11-28 06:00:06 +02:00
feat: environment stage
This commit is contained in:
parent
9730b5733a
commit
5ccd873a54
@ -41,6 +41,7 @@
|
||||
"react-redux": "^5.0.5",
|
||||
"react-router": "^4.1.1",
|
||||
"react-router-dom": "^4.1.1",
|
||||
"react-simple-table": "^1.0.1",
|
||||
"react-styled-flexboxgrid": "^2.0.1",
|
||||
"redux": "^3.6.0",
|
||||
"redux-actions": "^2.0.3",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Field } from 'redux-form';
|
||||
import styled from 'styled-components';
|
||||
import SimpleTable from 'react-simple-table';
|
||||
import { Row, Col } from 'react-styled-flexboxgrid';
|
||||
import { Dots2 } from 'styled-text-spinners';
|
||||
import Bundle from 'react-bundle';
|
||||
@ -48,9 +49,12 @@ const ButtonsRow = Row.extend`
|
||||
margin-bottom: ${remcalc(60)};
|
||||
`;
|
||||
|
||||
const Editor = ManifestEditor => ({ input, defaultValue }) =>
|
||||
const MEditor = ManifestEditor => ({ input, defaultValue }) =>
|
||||
<ManifestEditor mode="yaml" {...input} value={input.value || defaultValue} />;
|
||||
|
||||
const EEditor = ManifestEditor => ({ input, defaultValue }) =>
|
||||
<ManifestEditor mode="ini" {...input} value={input.value || defaultValue} />;
|
||||
|
||||
export const Name = ({ handleSubmit, onCancel, dirty }) =>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Row>
|
||||
@ -67,14 +71,7 @@ export const Name = ({ handleSubmit, onCancel, dirty }) =>
|
||||
</ButtonsRow>
|
||||
</form>;
|
||||
|
||||
export const Manifest = ({
|
||||
handleSubmit,
|
||||
onCancel,
|
||||
dirty,
|
||||
defaultValue,
|
||||
mode,
|
||||
loading
|
||||
}) =>
|
||||
export const Manifest = ({ handleSubmit, onCancel, dirty, defaultValue }) =>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Bundle load={() => import('joyent-manifest-editor')}>
|
||||
{ManifestEditor =>
|
||||
@ -82,7 +79,33 @@ export const Manifest = ({
|
||||
? <Field
|
||||
name="manifest"
|
||||
defaultValue={defaultValue}
|
||||
component={Editor(ManifestEditor)}
|
||||
component={MEditor(ManifestEditor)}
|
||||
/>
|
||||
: <Dots2 />}
|
||||
</Bundle>
|
||||
<ButtonsRow>
|
||||
<Button onClick={onCancel} secondary>Cancel</Button>
|
||||
<Button disabled={!dirty} type="submit">
|
||||
Environment
|
||||
</Button>
|
||||
</ButtonsRow>
|
||||
</form>;
|
||||
|
||||
export const Environment = ({
|
||||
handleSubmit,
|
||||
onCancel,
|
||||
dirty,
|
||||
defaultValue,
|
||||
loading
|
||||
}) =>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Bundle load={() => import('joyent-manifest-editor')}>
|
||||
{ManifestEditor =>
|
||||
ManifestEditor
|
||||
? <Field
|
||||
name="environment"
|
||||
defaultValue={defaultValue}
|
||||
component={EEditor(ManifestEditor)}
|
||||
/>
|
||||
: <Dots2 />}
|
||||
</Bundle>
|
||||
@ -95,11 +118,29 @@ export const Manifest = ({
|
||||
</form>;
|
||||
|
||||
export const Review = ({ handleSubmit, onCancel, dirty, ...state }) => {
|
||||
const serviceList = forceArray(state.services).map(({ name, image }) =>
|
||||
const serviceList = forceArray(state.services).map(({ name, config }) =>
|
||||
<ServiceCard key={name}>
|
||||
<Dl>
|
||||
<dt><ServiceName>{name}</ServiceName></dt>
|
||||
<dt><ImageTitle>Image:</ImageTitle> <Image>{image}</Image></dt>
|
||||
<dt><ImageTitle>Image:</ImageTitle> <Image>{config.image}</Image></dt>
|
||||
{config.environment.length
|
||||
? <dt><ImageTitle>Environment:</ImageTitle></dt>
|
||||
: undefined}
|
||||
{config.environment.length
|
||||
? <SimpleTable
|
||||
columns={[
|
||||
{
|
||||
columnHeader: 'Name',
|
||||
path: 'name'
|
||||
},
|
||||
{
|
||||
columnHeader: 'Value',
|
||||
path: 'value'
|
||||
}
|
||||
]}
|
||||
data={config.environment}
|
||||
/>
|
||||
: undefined}
|
||||
</Dl>
|
||||
</ServiceCard>
|
||||
);
|
||||
@ -136,7 +177,7 @@ export const Progress = ({ stage, create, edit }) => {
|
||||
</ProgressbarButton>
|
||||
</ProgressbarItem>;
|
||||
|
||||
const _manifestCompleted = stage === 'review';
|
||||
const _manifestCompleted = ['environment', 'review'].indexOf(stage) >= 0;
|
||||
const _manifestActive = create ? stage === 'manifest' : stage === 'edit';
|
||||
|
||||
const _manifest = (
|
||||
@ -147,7 +188,22 @@ export const Progress = ({ stage, create, edit }) => {
|
||||
active={_manifestActive}
|
||||
first={edit}
|
||||
>
|
||||
Define services
|
||||
Define Services
|
||||
</ProgressbarButton>
|
||||
</ProgressbarItem>
|
||||
);
|
||||
|
||||
const _environmentCompleted = stage === 'review';
|
||||
const _environmentActive = stage === 'environment';
|
||||
|
||||
const _environment = (
|
||||
<ProgressbarItem>
|
||||
<ProgressbarButton
|
||||
zIndex="8"
|
||||
completed={_environmentCompleted}
|
||||
active={_environmentActive}
|
||||
>
|
||||
Define Environment
|
||||
</ProgressbarButton>
|
||||
</ProgressbarItem>
|
||||
);
|
||||
@ -156,7 +212,7 @@ export const Progress = ({ stage, create, edit }) => {
|
||||
|
||||
const _review = (
|
||||
<ProgressbarItem>
|
||||
<ProgressbarButton zIndex="8" active={stage === 'review'} last>
|
||||
<ProgressbarButton zIndex="7" active={_reviewActive} last>
|
||||
Review and deploy
|
||||
</ProgressbarButton>
|
||||
</ProgressbarItem>
|
||||
@ -166,6 +222,7 @@ export const Progress = ({ stage, create, edit }) => {
|
||||
<Progressbar>
|
||||
{_name}
|
||||
{_manifest}
|
||||
{_environment}
|
||||
{_review}
|
||||
</Progressbar>
|
||||
);
|
||||
|
@ -96,6 +96,7 @@ const ServiceListItem = ({
|
||||
</CardDescription>
|
||||
<CardOptions onClick={handleCardOptionsClick} />
|
||||
</StyledCardHeader>;
|
||||
|
||||
const view = children
|
||||
? <CardGroupView>
|
||||
{children}
|
||||
|
@ -12,7 +12,12 @@ import DeploymentGroupProvisionMutation from '@graphql/DeploymentGroupProvision.
|
||||
import DeploymentGroupConfigQuery from '@graphql/DeploymentGroupConfig.gql';
|
||||
|
||||
import { client } from '@state/store';
|
||||
import { Name, Manifest, Review } from '@components/deployment-groups/create';
|
||||
import {
|
||||
Name,
|
||||
Manifest,
|
||||
Environment,
|
||||
Review
|
||||
} from '@components/deployment-groups/create';
|
||||
|
||||
// TODO: move state to redux. why: because in redux we can cache transactional
|
||||
// state between refreshes
|
||||
@ -51,6 +56,12 @@ class DeploymentGroupEditOrCreate extends Component {
|
||||
forceUnregisterOnUnmount: true
|
||||
})(Manifest);
|
||||
|
||||
const EnvironmentForm = reduxForm({
|
||||
form: `${type}-deployment-group`,
|
||||
destroyOnUnmount: true,
|
||||
forceUnregisterOnUnmount: true
|
||||
})(Environment);
|
||||
|
||||
const ReviewForm = reduxForm({
|
||||
form: `${type}-deployment-group`,
|
||||
destroyOnUnmount: true,
|
||||
@ -62,17 +73,20 @@ class DeploymentGroupEditOrCreate extends Component {
|
||||
manifestStage: create ? 'manifest' : 'edit',
|
||||
name: '',
|
||||
manifest: '',
|
||||
environment: '',
|
||||
services: [],
|
||||
loading: false,
|
||||
error: null,
|
||||
NameForm,
|
||||
ManifestForm,
|
||||
EnvironmentForm,
|
||||
ReviewForm
|
||||
};
|
||||
|
||||
this.stages = {
|
||||
name: create && this.renderNameForm.bind(this),
|
||||
[create ? 'manifest' : 'edit']: this.renderManifestEditor.bind(this),
|
||||
environment: this.renderEnvironmentEditor.bind(this),
|
||||
review: this.renderReview.bind(this)
|
||||
};
|
||||
|
||||
@ -80,6 +94,7 @@ class DeploymentGroupEditOrCreate extends Component {
|
||||
type === 'create' && this.handleNameSubmit.bind(this);
|
||||
|
||||
this.handleManifestSubmit = this.handleManifestSubmit.bind(this);
|
||||
this.handleEnvironmentSubmit = this.handleEnvironmentSubmit.bind(this);
|
||||
this.handleReviewSubmit = this.handleReviewSubmit.bind(this);
|
||||
this.handleCancel = this.handleCancel.bind(this);
|
||||
|
||||
@ -117,7 +132,7 @@ class DeploymentGroupEditOrCreate extends Component {
|
||||
};
|
||||
|
||||
provision = async deploymentGroupId => {
|
||||
const { manifest } = this.state;
|
||||
const { manifest, environment } = this.state;
|
||||
const { provisionManifest } = this.props;
|
||||
|
||||
const [err] = await intercept(
|
||||
@ -125,6 +140,7 @@ class DeploymentGroupEditOrCreate extends Component {
|
||||
deploymentGroupId,
|
||||
type: 'COMPOSE',
|
||||
format: 'YAML',
|
||||
environment,
|
||||
raw: manifest
|
||||
})
|
||||
);
|
||||
@ -145,16 +161,24 @@ class DeploymentGroupEditOrCreate extends Component {
|
||||
}
|
||||
|
||||
handleManifestSubmit({ manifest = '' }) {
|
||||
const { name } = this.state;
|
||||
this.setState({ manifest }, () => {
|
||||
this.redirect({ stage: 'environment', prog: true });
|
||||
});
|
||||
}
|
||||
|
||||
handleEnvironmentSubmit({ environment = '' }) {
|
||||
const { name, manifest } = this.state;
|
||||
|
||||
const getConfig = async () => {
|
||||
const [err, conf] = await intercept(
|
||||
client.query({
|
||||
query: DeploymentGroupConfigQuery,
|
||||
fetchPolicy: 'network-only',
|
||||
variables: {
|
||||
deploymentGroupName: name,
|
||||
type: 'COMPOSE',
|
||||
format: 'YAML',
|
||||
environment,
|
||||
raw: manifest
|
||||
}
|
||||
})
|
||||
@ -174,7 +198,7 @@ class DeploymentGroupEditOrCreate extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
this.setState({ manifest, loading: true }, getConfig);
|
||||
this.setState({ environment, loading: true }, getConfig);
|
||||
}
|
||||
|
||||
handleReviewSubmit() {
|
||||
@ -237,6 +261,18 @@ class DeploymentGroupEditOrCreate extends Component {
|
||||
defaultValue={this.props.manifest}
|
||||
onSubmit={this.handleManifestSubmit}
|
||||
onCancel={this.handleCancel}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
renderEnvironmentEditor() {
|
||||
const { EnvironmentForm } = this.state;
|
||||
|
||||
return (
|
||||
<EnvironmentForm
|
||||
defaultValue={this.props.environment}
|
||||
onSubmit={this.handleEnvironmentSubmit}
|
||||
onCancel={this.handleCancel}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
);
|
||||
@ -276,10 +312,20 @@ class DeploymentGroupEditOrCreate extends Component {
|
||||
return this.redirect({ stage: defaultStage });
|
||||
}
|
||||
|
||||
if (stage === 'review' && !this.state.manifest) {
|
||||
if (stage === 'environment' && !this.state.manifest) {
|
||||
return this.redirect({ stage: manifestStage });
|
||||
}
|
||||
|
||||
if (stage === 'review' && !this.state.environment) {
|
||||
if (!this.state.manifest) {
|
||||
return this.redirect({ stage: manifestStage });
|
||||
}
|
||||
|
||||
if (!this.state.environment) {
|
||||
return this.redirect({ stage: 'environment' });
|
||||
}
|
||||
}
|
||||
|
||||
return this.stages[stage]();
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,22 @@
|
||||
#import "./ServiceInfo.gql"
|
||||
|
||||
query config($deploymentGroupName: String!, $type: ManifestType!, $format: ManifestFormat!, $raw: String!) {
|
||||
config(deploymentGroupName: $deploymentGroupName, type: $type, format: $format, raw: $raw) {
|
||||
image
|
||||
query config($deploymentGroupName: String!, $type: ManifestType!, $format: ManifestFormat!, $environment: String!, $raw: String!) {
|
||||
config(deploymentGroupName: $deploymentGroupName, type: $type, format: $format, environment: $environment, raw: $raw) {
|
||||
...ServiceInfo
|
||||
config {
|
||||
id
|
||||
image
|
||||
ports
|
||||
environment {
|
||||
id
|
||||
name
|
||||
value
|
||||
}
|
||||
labels {
|
||||
id
|
||||
name
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
mutation provisionManifest($deploymentGroupId: ID!, $type: ManifestType!, $format: ManifestFormat!, $raw: String!) {
|
||||
provisionManifest(deploymentGroupId: $deploymentGroupId, type: $type, format: $format, raw: $raw) {
|
||||
mutation provisionManifest($deploymentGroupId: ID!, $type: ManifestType!, $format: ManifestFormat!, $environment: String!, $raw: String!) {
|
||||
provisionManifest(deploymentGroupId: $deploymentGroupId, type: $type, format: $format, environment: $environment, raw: $raw) {
|
||||
scale {
|
||||
serviceName
|
||||
replicas
|
||||
|
@ -68,15 +68,14 @@ const activeInstanceStatuses = [
|
||||
'INCOMPLETE'
|
||||
];
|
||||
|
||||
const getInstanceStatuses = (service) => {
|
||||
|
||||
const getInstanceStatuses = service => {
|
||||
const instanceStatuses = service.instances.reduce((statuses, instance) => {
|
||||
// if (instance.status !== 'RUNNING') {
|
||||
if (statuses[instance.status]) {
|
||||
statuses[instance.status]++;
|
||||
} else {
|
||||
statuses[instance.status] = 1;
|
||||
}
|
||||
if (statuses[instance.status]) {
|
||||
statuses[instance.status]++;
|
||||
} else {
|
||||
statuses[instance.status] = 1;
|
||||
}
|
||||
// }
|
||||
return statuses;
|
||||
}, {});
|
||||
@ -85,31 +84,35 @@ const getInstanceStatuses = (service) => {
|
||||
status,
|
||||
count: instanceStatuses[status]
|
||||
}));
|
||||
}
|
||||
|
||||
const getInstancesActive = (instanceStatuses) => {
|
||||
return instanceStatuses.reduce((active, instanceStatus) =>
|
||||
activeInstanceStatuses.indexOf(instanceStatus.status) === -1 ?
|
||||
active : true, false);
|
||||
}
|
||||
|
||||
const getService = (service, index) => {
|
||||
|
||||
const statuses = getInstanceStatuses(service);
|
||||
const instancesActive = getInstancesActive(statuses);
|
||||
const instanceStatuses = statuses.length === 1 && statuses[0].status === 'RUNNING' ?
|
||||
[] : statuses;
|
||||
return ({
|
||||
index,
|
||||
...service,
|
||||
instanceStatuses,
|
||||
instancesActive,
|
||||
isConsul: service.slug === 'consul'
|
||||
});
|
||||
};
|
||||
|
||||
const processServices = (services) => {
|
||||
const getInstancesActive = instanceStatuses => {
|
||||
return instanceStatuses.reduce(
|
||||
(active, instanceStatus) =>
|
||||
activeInstanceStatuses.indexOf(instanceStatus.status) === -1
|
||||
? active
|
||||
: true,
|
||||
false
|
||||
);
|
||||
};
|
||||
|
||||
const getService = (service, index) => {
|
||||
const statuses = getInstanceStatuses(service);
|
||||
const instancesActive = getInstancesActive(statuses);
|
||||
const instanceStatuses = statuses.length === 1 &&
|
||||
statuses[0].status === 'RUNNING'
|
||||
? []
|
||||
: statuses;
|
||||
return {
|
||||
index,
|
||||
...service,
|
||||
instanceStatuses,
|
||||
instancesActive,
|
||||
isConsul: service.slug === 'consul'
|
||||
};
|
||||
};
|
||||
|
||||
const processServices = services => {
|
||||
return forceArray(services).reduce((ss, s, i) => {
|
||||
if (s.parent) {
|
||||
const parents = ss.filter(parentS => parentS.id === s.parent);
|
||||
@ -124,7 +127,9 @@ const processServices = (services) => {
|
||||
parent.children = [];
|
||||
}
|
||||
const child = getService(s, i);
|
||||
parent.instancesActive = parent.instancesActive ? true : child.instancesActive;
|
||||
parent.instancesActive = parent.instancesActive
|
||||
? true
|
||||
: child.instancesActive;
|
||||
parent.children.push(child);
|
||||
} else {
|
||||
const serviceIndex = ss.findIndex(existingS => existingS.id === s.id);
|
||||
@ -141,19 +146,22 @@ const processServices = (services) => {
|
||||
}, []);
|
||||
};
|
||||
|
||||
const processServicesForTopology = (services) => {
|
||||
|
||||
const processServicesForTopology = services => {
|
||||
const processedServices = processServices(services);
|
||||
|
||||
const connectedServices = processedServices.reduce((connections, service) =>
|
||||
service.connections && service.connections.length ?
|
||||
connections.concat(service.connections).concat(service.id) : connections, []);
|
||||
const connectedServices = processedServices.reduce(
|
||||
(connections, service) =>
|
||||
service.connections && service.connections.length
|
||||
? connections.concat(service.connections).concat(service.id)
|
||||
: connections,
|
||||
[]
|
||||
);
|
||||
|
||||
return processedServices.map(service => ({
|
||||
...service,
|
||||
connected: connectedServices.indexOf(service.id) !== -1
|
||||
}));
|
||||
}
|
||||
...service,
|
||||
connected: connectedServices.indexOf(service.id) !== -1
|
||||
}));
|
||||
};
|
||||
|
||||
export {
|
||||
deploymentGroupBySlug as deploymentGroupBySlugSelector,
|
||||
|
@ -1,6 +1,3 @@
|
||||
scalar Date
|
||||
scalar Object
|
||||
|
||||
type Portal {
|
||||
id: ID!
|
||||
user: User!
|
||||
@ -36,6 +33,7 @@ type DeploymentGroup {
|
||||
}
|
||||
|
||||
type ServiceScale {
|
||||
id: ID!
|
||||
serviceName: String!
|
||||
replicas: Int!
|
||||
}
|
||||
@ -50,6 +48,7 @@ enum ConvergenceActionType {
|
||||
}
|
||||
|
||||
type ConvergenceAction {
|
||||
id: ID!
|
||||
type: ConvergenceActionType!
|
||||
service: String! # service name
|
||||
toProcess: Int, # merely used for book keeping
|
||||
@ -58,6 +57,7 @@ type ConvergenceAction {
|
||||
}
|
||||
|
||||
type Version {
|
||||
id: ID!
|
||||
manifest: Manifest!
|
||||
scale(serviceName: String): [ServiceScale]!
|
||||
plan: [ConvergenceAction]
|
||||
@ -79,8 +79,8 @@ type Manifest {
|
||||
id: ID!
|
||||
type: ManifestType!
|
||||
format: ManifestFormat!
|
||||
environment: String!
|
||||
raw: String!
|
||||
obj: Object
|
||||
}
|
||||
|
||||
enum ServiceStatus {
|
||||
@ -95,6 +95,21 @@ enum ServiceStatus {
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
type KeyValue {
|
||||
id: ID!
|
||||
name: String!
|
||||
value: String!
|
||||
}
|
||||
|
||||
type ServiceConfig {
|
||||
id: ID!
|
||||
package: Package # we don't have this in current mock data
|
||||
environment: [KeyValue]
|
||||
image: String # used only for config
|
||||
labels: [KeyValue]
|
||||
ports: [String]
|
||||
}
|
||||
|
||||
# immutable
|
||||
type Service {
|
||||
id: ID! # unique id for db row
|
||||
@ -102,11 +117,9 @@ type Service {
|
||||
name: String! # human readable name
|
||||
slug: String!
|
||||
instances(name: String, machineId: ID, status: InstanceStatus): [Instance]!
|
||||
connections: [String!] # list of serviceIds
|
||||
connections: [String] # list of serviceIds
|
||||
parent: ID # parent service id
|
||||
package: Package! # we don't have this in current mock data,
|
||||
environment: [Environment]
|
||||
image: String # used only for config
|
||||
config: ServiceConfig
|
||||
status: ServiceStatus
|
||||
}
|
||||
|
||||
@ -124,12 +137,6 @@ type Package {
|
||||
group: String!
|
||||
}
|
||||
|
||||
# environment variables
|
||||
type Environment {
|
||||
name: String!
|
||||
value: String!
|
||||
}
|
||||
|
||||
enum InstanceStatus {
|
||||
PROVISIONING
|
||||
READY
|
||||
@ -184,7 +191,7 @@ type Query {
|
||||
datacenter(id: ID, region: String): Datacenter
|
||||
datacenters: [Datacenter]
|
||||
|
||||
config(deploymentGroupName: String!, type: ManifestType!, format: ManifestFormat!, raw: String!): [Service]
|
||||
config(deploymentGroupName: String!, type: ManifestType!, format: ManifestFormat!, environment: String!, raw: String!): [Service]
|
||||
importableDeploymentGroups: [DeploymentGroup]
|
||||
}
|
||||
|
||||
@ -192,7 +199,7 @@ type Mutation {
|
||||
createDeploymentGroup(name: String!): DeploymentGroup
|
||||
updateDeploymentGroup(id: ID!, name: String!): DeploymentGroup
|
||||
|
||||
provisionManifest(deploymentGroupId: ID!, type: ManifestType!, format: ManifestFormat!, raw: String!): Version
|
||||
provisionManifest(deploymentGroupId: ID!, type: ManifestType!, format: ManifestFormat!, environment: String!, raw: String!): Version
|
||||
scale(serviceId: ID!, replicas: Int!): Version
|
||||
|
||||
stopServices(ids: [ID]!): [Service]
|
||||
|
@ -22,13 +22,17 @@ module.exports = class DockerComposeClient extends EventEmitter {
|
||||
return this.client.close();
|
||||
}
|
||||
|
||||
provision({ projectName, manifest }, cb) {
|
||||
// eslint-disable-next-line camelcase
|
||||
return this._invoke('up', { project_name: projectName }, manifest, cb);
|
||||
provision({ projectName, environment, manifest }, cb) {
|
||||
return this._invoke('up', {
|
||||
// eslint-disable-next-line camelcase
|
||||
project_name: projectName,
|
||||
environment
|
||||
}, manifest, cb);
|
||||
}
|
||||
|
||||
scale({ projectName, services, manifest }, cb) {
|
||||
scale({ projectName, services, environment, manifest }, cb) {
|
||||
const options = {
|
||||
environment,
|
||||
// eslint-disable-next-line camelcase
|
||||
project_name: projectName,
|
||||
services: Object.keys(services).map(name => ({
|
||||
@ -40,10 +44,11 @@ module.exports = class DockerComposeClient extends EventEmitter {
|
||||
return this._invoke('scale', options, manifest, cb);
|
||||
}
|
||||
|
||||
config({ projectName, manifest }, cb) {
|
||||
config({ projectName, environment, manifest }, cb) {
|
||||
const options = {
|
||||
// eslint-disable-next-line camelcase
|
||||
project_name: projectName
|
||||
project_name: projectName,
|
||||
environment
|
||||
};
|
||||
|
||||
return this._invoke('config', options, manifest, cb);
|
||||
|
@ -4,6 +4,7 @@ import 'codemirror/addon/fold/foldgutter.css';
|
||||
import 'codemirror/addon/lint/lint.css';
|
||||
import 'codemirror/mode/yaml/yaml';
|
||||
import 'codemirror/mode/javascript/javascript';
|
||||
import 'codemirror/mode/properties/properties';
|
||||
import 'codemirror/addon/edit/closebrackets';
|
||||
import 'codemirror/addon/edit/matchbrackets';
|
||||
import 'codemirror/addon/fold/foldcode';
|
||||
@ -60,7 +61,8 @@ class ManifestEditor extends Component {
|
||||
name: 'javascript',
|
||||
json: true
|
||||
},
|
||||
yaml: 'yaml'
|
||||
yaml: 'yaml',
|
||||
ini: 'properties'
|
||||
};
|
||||
|
||||
return Object.assign({}, options, {
|
||||
|
@ -13,7 +13,6 @@ const Hoek = require('hoek');
|
||||
const Triton = require('triton');
|
||||
const ParamCase = require('param-case');
|
||||
const Penseur = require('penseur');
|
||||
const { DEPLOYMENT_GROUP, SERVICE, HASH } = require('../watch');
|
||||
const UniqBy = require('lodash.uniqby');
|
||||
const Find = require('lodash.find');
|
||||
const Get = require('lodash.get');
|
||||
@ -24,6 +23,7 @@ const VAsync = require('vasync');
|
||||
|
||||
// local modules
|
||||
const Transform = require('./transform');
|
||||
const { DEPLOYMENT_GROUP, SERVICE, HASH } = require('../watch');
|
||||
|
||||
|
||||
const NON_IMPORTABLE_STATES = [
|
||||
@ -153,7 +153,11 @@ class Data extends EventEmitter {
|
||||
const portal = portals.shift();
|
||||
|
||||
// Sub query/filter for deploymentGroups
|
||||
const deploymentGroups = (args) => {
|
||||
const deploymentGroups = (args, cb) => {
|
||||
if (typeof cb === 'function') {
|
||||
return this.getDeploymentGroups(args, cb);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.getDeploymentGroups(args, internals.resolveCb(resolve, reject));
|
||||
});
|
||||
@ -372,7 +376,7 @@ class Data extends EventEmitter {
|
||||
}
|
||||
|
||||
if (!deploymentGroups || !deploymentGroups.length) {
|
||||
return cb(null, {});
|
||||
return cb();
|
||||
}
|
||||
|
||||
cb(null, Transform.fromDeploymentGroup(this._getDeploymentGroupFns(deploymentGroups[0])));
|
||||
@ -512,6 +516,7 @@ class Data extends EventEmitter {
|
||||
]);
|
||||
|
||||
return {
|
||||
id: Uuid(),
|
||||
serviceName: name,
|
||||
replicas: Number.isFinite(currentScale) ? currentScale : 1
|
||||
};
|
||||
@ -554,6 +559,7 @@ class Data extends EventEmitter {
|
||||
});
|
||||
|
||||
return {
|
||||
id: Uuid(),
|
||||
serviceName: name,
|
||||
replicas: existingMachines.length ? existingMachines.length : 1
|
||||
};
|
||||
@ -565,7 +571,7 @@ class Data extends EventEmitter {
|
||||
this._listMachines(deploymentGroupName, handleMachinesList);
|
||||
}
|
||||
|
||||
scale ({ serviceId, replicas }, cb) {
|
||||
scale ({ serviceId, environment, replicas }, cb) {
|
||||
Hoek.assert(serviceId, 'service id is required');
|
||||
Hoek.assert(typeof replicas === 'number' && replicas >= 0, 'replicas must be a number no less than 0');
|
||||
|
||||
@ -636,6 +642,7 @@ class Data extends EventEmitter {
|
||||
|
||||
this._dockerCompose.scale({
|
||||
projectName: ctx.deploymentGroup.name,
|
||||
environment,
|
||||
services: {
|
||||
[ctx.service.name]: replicas
|
||||
},
|
||||
@ -647,6 +654,7 @@ class Data extends EventEmitter {
|
||||
const getNewScale = () => {
|
||||
return ctx.currentScale.map(({ serviceName, replicas }) => {
|
||||
return {
|
||||
id: Uuid(),
|
||||
serviceName: serviceName,
|
||||
replicas: serviceName === ctx.service.name ?
|
||||
(ctx.serviceScale + ctx.diff) :
|
||||
@ -661,6 +669,7 @@ class Data extends EventEmitter {
|
||||
deploymentGroupId: ctx.deploymentGroup.id,
|
||||
scale: getNewScale(),
|
||||
plan: [{
|
||||
id: Uuid(),
|
||||
type: 'REMOVE',
|
||||
service: ctx.service.name,
|
||||
toProcess: Math.abs(ctx.diff),
|
||||
@ -683,6 +692,7 @@ class Data extends EventEmitter {
|
||||
deploymentGroupId: ctx.deploymentGroup.id,
|
||||
scale: getNewScale(),
|
||||
plan: [{
|
||||
id: Uuid(),
|
||||
type: 'CREATE',
|
||||
service: ctx.service.name,
|
||||
toProcess: Math.abs(ctx.diff),
|
||||
@ -908,6 +918,7 @@ class Data extends EventEmitter {
|
||||
|
||||
if (!provision) {
|
||||
return {
|
||||
id: Uuid(),
|
||||
type: 'REMOVE',
|
||||
service: name,
|
||||
toProcess: machines.length,
|
||||
@ -918,6 +929,7 @@ class Data extends EventEmitter {
|
||||
const ActionMap = {
|
||||
'NOOP': () => {
|
||||
return {
|
||||
id: Uuid(),
|
||||
type: 'NOOP',
|
||||
service: name,
|
||||
machines
|
||||
@ -925,6 +937,7 @@ class Data extends EventEmitter {
|
||||
},
|
||||
'CREATE': () => {
|
||||
return {
|
||||
id: Uuid(),
|
||||
type: 'CREATE',
|
||||
service: name,
|
||||
toProcess: scale,
|
||||
@ -933,6 +946,7 @@ class Data extends EventEmitter {
|
||||
},
|
||||
'RECREATE': () => {
|
||||
return {
|
||||
id: Uuid(),
|
||||
type: 'CREATE',
|
||||
service: name,
|
||||
toProcess: machines.length,
|
||||
@ -941,6 +955,7 @@ class Data extends EventEmitter {
|
||||
},
|
||||
'START': () => {
|
||||
return {
|
||||
id: Uuid(),
|
||||
type: 'START',
|
||||
service: name,
|
||||
machines
|
||||
@ -1077,12 +1092,17 @@ class Data extends EventEmitter {
|
||||
const action = Get(provision, 'plan.action', 'noop').toUpperCase();
|
||||
const service = services.shift();
|
||||
|
||||
const { config } = Find(ctx.config, ['name', serviceName], {
|
||||
config: {}
|
||||
});
|
||||
|
||||
const payload = {
|
||||
hash: provision.hash,
|
||||
deploymentGroupId: ctx.currentDeploymentGroup.id,
|
||||
name: serviceName,
|
||||
slug: ParamCase(serviceName),
|
||||
status: ServiceStatusFromPlan[action]
|
||||
status: ServiceStatusFromPlan[action],
|
||||
config
|
||||
};
|
||||
|
||||
return !service ?
|
||||
@ -1133,6 +1153,7 @@ class Data extends EventEmitter {
|
||||
|
||||
this._dockerCompose.provision({
|
||||
projectName: ctx.currentDeploymentGroup.name,
|
||||
environment: clientManifest.environment,
|
||||
manifest: ctx.newManifest.raw
|
||||
}, handleProvisionResponse);
|
||||
});
|
||||
@ -1830,23 +1851,19 @@ class Data extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
updateInstance ({ id, status, healthy}, cb) {
|
||||
const changes = { id };
|
||||
updateInstance (clientInstance, cb) {
|
||||
const instance = Transform.toInstance(clientInstance);
|
||||
|
||||
if (typeof healthy === 'boolean') {
|
||||
changes.healthy = healthy;
|
||||
if (typeof instance.healthy !== 'boolean') {
|
||||
instance.healthy = null;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
changes.status = status;
|
||||
}
|
||||
|
||||
this._db.instances.update([changes], (err) => {
|
||||
this._db.instances.update([instance], (err) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
|
||||
this.getInstance({ id }, cb);
|
||||
this.getInstance({ id: instance.id }, cb);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1989,7 +2006,7 @@ class Data extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
getConfig ({deploymentGroupName = '', type = '', format = '', raw = '' }, cb) {
|
||||
getConfig ({deploymentGroupName = '', type = '', format = '', environment = '', raw = '' }, cb) {
|
||||
if (type.toUpperCase() !== 'COMPOSE') {
|
||||
return cb(new Error('"COMPOSE" is the only `type` supported'));
|
||||
}
|
||||
@ -2002,6 +2019,7 @@ class Data extends EventEmitter {
|
||||
|
||||
this._dockerCompose.config({
|
||||
projectName: deploymentGroupName,
|
||||
environment,
|
||||
manifest: raw
|
||||
}, (err, config = {}) => {
|
||||
if (err) {
|
||||
@ -2021,15 +2039,34 @@ class Data extends EventEmitter {
|
||||
}
|
||||
|
||||
cb(null, Object.keys(services).reduce((acc, serviceName) => {
|
||||
const environment = Get(services, `${serviceName}.environment`, {});
|
||||
const labels = Get(services, `${serviceName}.labels`, {});
|
||||
const ports = Get(services, `${serviceName}.ports`, []);
|
||||
const image = Get(services, `${serviceName}.image`, '');
|
||||
|
||||
const toKeyValue = (v) => {
|
||||
return Object.keys(v).map((key) => {
|
||||
return {
|
||||
id: Uuid(),
|
||||
name: key,
|
||||
value: v[key]
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
return acc.concat([{
|
||||
id: Uuid(),
|
||||
hash: Uuid(),
|
||||
name: serviceName,
|
||||
slug: ParamCase(serviceName),
|
||||
instances: [],
|
||||
package: {},
|
||||
active: true,
|
||||
image: services[serviceName].image
|
||||
config: {
|
||||
id: Uuid(),
|
||||
environment: toKeyValue(environment),
|
||||
image: image,
|
||||
labels: toKeyValue(labels),
|
||||
ports: ports
|
||||
}
|
||||
}]);
|
||||
}, []));
|
||||
});
|
||||
|
@ -69,12 +69,10 @@ exports.fromService = function ({ service, instances, packages }) {
|
||||
deploymentGroupId: service.deployment_group_id,
|
||||
name: service.name,
|
||||
slug: service.slug,
|
||||
environment: service.environment || [],
|
||||
instances,
|
||||
currentMetrics: [],
|
||||
connections: service.service_dependency_ids,
|
||||
package: packages ? exports.fromPackage(packages) : {},
|
||||
parent: service.parent_id || '',
|
||||
parent: service.parent_id,
|
||||
config: service.config ? service.config : undefined,
|
||||
status: service.status,
|
||||
hasPlan: service.has_plan
|
||||
};
|
||||
@ -88,15 +86,14 @@ exports.toService = function (clientService) {
|
||||
deployment_group_id: clientService.deploymentGroupId,
|
||||
name: clientService.name,
|
||||
slug: clientService.slug,
|
||||
environment: clientService.environment,
|
||||
instance_ids: clientService.instances ?
|
||||
clientService.instances.map((instance) => {
|
||||
return instance.id;
|
||||
}) :
|
||||
undefined,
|
||||
service_dependency_ids: clientService.connections,
|
||||
package_id: clientService.package ? clientService.package.id : undefined,
|
||||
parent_id: clientService.parent ? clientService.parent : undefined,
|
||||
config: clientService.config ? clientService.config : undefined,
|
||||
status: clientService.status,
|
||||
has_plan: clientService.hasPlan
|
||||
});
|
||||
@ -133,6 +130,7 @@ exports.toManifest = function (clientManifest) {
|
||||
created: clientManifest.created || Date.now(),
|
||||
type: clientManifest.type,
|
||||
format: clientManifest.format,
|
||||
environment: clientManifest.environment,
|
||||
raw: clientManifest.raw,
|
||||
json: clientManifest.json || Yamljs.parse(clientManifest.raw)
|
||||
};
|
||||
@ -145,6 +143,7 @@ exports.fromManifest = function (manifest) {
|
||||
created: manifest.created,
|
||||
type: manifest.type,
|
||||
format: manifest.format,
|
||||
environment: manifest.environment,
|
||||
raw: manifest.raw,
|
||||
json: manifest.json
|
||||
};
|
||||
|
90
yarn.lock
90
yarn.lock
@ -123,8 +123,8 @@ acorn@^4.0.3:
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
|
||||
|
||||
acorn@^5.0.0, acorn@^5.0.1, acorn@^5.0.3:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d"
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75"
|
||||
|
||||
add-stream@^1.0.0:
|
||||
version "1.0.0"
|
||||
@ -403,8 +403,8 @@ arr-exclude@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/arr-exclude/-/arr-exclude-1.0.0.tgz#dfc7c2e552a270723ccda04cf3128c8cbfe5c631"
|
||||
|
||||
arr-flatten@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.3.tgz#a274ed85ac08849b6bd7847c4580745dc51adfb1"
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
|
||||
|
||||
arr-union@^3.0.0:
|
||||
version "3.1.0"
|
||||
@ -497,6 +497,10 @@ ast-types@0.9.0:
|
||||
version "0.9.0"
|
||||
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:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
|
||||
@ -2902,6 +2906,10 @@ deep-extend@~0.4.0:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
|
||||
|
||||
deep-get-set@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/deep-get-set/-/deep-get-set-1.1.0.tgz#47bba2008a3fde9c753dcbe61a36241606d9836f"
|
||||
|
||||
deep-is@~0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
||||
@ -2986,8 +2994,8 @@ diff-match-patch@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.0.tgz#1cc3c83a490d67f95d91e39f6ad1f2e086b63048"
|
||||
|
||||
diff@3.x.x, diff@^3.0.0, diff@^3.0.1, diff@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.0.tgz#056695150d7aa93237ca7e378ac3b1682b7963b9"
|
||||
|
||||
diffie-hellman@^5.0.0:
|
||||
version "5.0.2"
|
||||
@ -3329,7 +3337,7 @@ eslint-import-resolver-node@^0.3.1:
|
||||
debug "^2.6.8"
|
||||
resolve "^1.2.0"
|
||||
|
||||
eslint-module-utils@^2.0.0:
|
||||
eslint-module-utils@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449"
|
||||
dependencies:
|
||||
@ -3352,15 +3360,15 @@ eslint-plugin-hapi@4.x.x:
|
||||
no-arrowception "1.x.x"
|
||||
|
||||
eslint-plugin-import@^2.3.0:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.6.1.tgz#f580be62bb809421d46e338372764afcc9f59bf6"
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz#21de33380b9efb55f5ef6d2e210ec0e07e7fa69f"
|
||||
dependencies:
|
||||
builtin-modules "^1.1.1"
|
||||
contains-path "^0.1.0"
|
||||
debug "^2.6.8"
|
||||
doctrine "1.5.0"
|
||||
eslint-import-resolver-node "^0.3.1"
|
||||
eslint-module-utils "^2.0.0"
|
||||
eslint-module-utils "^2.1.1"
|
||||
has "^1.0.1"
|
||||
lodash.cond "^4.3.0"
|
||||
minimatch "^3.0.3"
|
||||
@ -3498,7 +3506,7 @@ esprima@^2.6.0, esprima@~2.7.1:
|
||||
version "2.7.3"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
|
||||
|
||||
@ -4437,6 +4445,10 @@ hoist-non-react-statics@^1.0.3, hoist-non-react-statics@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb"
|
||||
|
||||
hoist-non-react-statics@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.0.0.tgz#843180515e0281952b08f41c620ca74870c7e354"
|
||||
|
||||
home-or-tmp@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
|
||||
@ -5385,8 +5397,8 @@ json5@0.5.x, json5@^0.5.0, json5@^0.5.1:
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
|
||||
|
||||
jsonfile@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.0.tgz#92e7c7444e5ffd5fa32e6a9ae8b85034df8347d0"
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66"
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
@ -5522,8 +5534,8 @@ lerna-wizard@ramitos/lerna-wizard#7bcdc11:
|
||||
inquirer "^3.0.2"
|
||||
|
||||
lerna@^2.0.0-rc.5:
|
||||
version "2.0.0-rc.5"
|
||||
resolved "https://registry.yarnpkg.com/lerna/-/lerna-2.0.0-rc.5.tgz#b59d168caaac6e3443078c1bce194208c9aa3090"
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lerna/-/lerna-2.0.0.tgz#49a72fe70e06aebfd7ea23efb2ab41abe60ebeea"
|
||||
dependencies:
|
||||
async "^1.5.0"
|
||||
chalk "^1.1.1"
|
||||
@ -5706,6 +5718,10 @@ lodash.difference@^4.3.0, lodash.difference@^4.4.0, lodash.difference@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
|
||||
|
||||
lodash.differenceby@^4.8.0:
|
||||
version "4.8.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.differenceby/-/lodash.differenceby-4.8.0.tgz#cfd59e94353af5de51da5d302ca4ebff33faac57"
|
||||
|
||||
lodash.find@^4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1"
|
||||
@ -7250,13 +7266,13 @@ rc@1.1.7, rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
react-apollo@^1.4.2:
|
||||
version "1.4.2"
|
||||
resolved "https://registry.yarnpkg.com/react-apollo/-/react-apollo-1.4.2.tgz#e8ee035310b564fd1b42ee7e4f116086b5b06834"
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/react-apollo/-/react-apollo-1.4.3.tgz#be18bfe7f6609263f3ff623308f88108152a7573"
|
||||
dependencies:
|
||||
apollo-client "^1.4.0"
|
||||
graphql-anywhere "^3.0.0"
|
||||
graphql-tag "^2.0.0"
|
||||
hoist-non-react-statics "^1.2.0"
|
||||
hoist-non-react-statics "^2.0.0"
|
||||
invariant "^2.2.1"
|
||||
lodash.flatten "^4.2.0"
|
||||
lodash.isequal "^4.1.1"
|
||||
@ -7351,6 +7367,12 @@ react-router@^4.1.1:
|
||||
prop-types "^15.5.4"
|
||||
warning "^3.0.0"
|
||||
|
||||
react-simple-table@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react-simple-table/-/react-simple-table-1.0.1.tgz#941390bd68eca63d028c1873bd90772a21143b9c"
|
||||
dependencies:
|
||||
deep-get-set "^1.0.0"
|
||||
|
||||
react-styled-flexboxgrid@^2.0.1:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/react-styled-flexboxgrid/-/react-styled-flexboxgrid-2.0.3.tgz#308a8bbc80b1737a65f4ccf35d02afe20932a2f2"
|
||||
@ -7529,7 +7551,7 @@ readline2@^1.0.1:
|
||||
is-fullwidth-code-point "^1.0.0"
|
||||
mute-stream "0.0.5"
|
||||
|
||||
recast@0.11.12, recast@^0.11.5:
|
||||
recast@0.11.12:
|
||||
version "0.11.12"
|
||||
resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.12.tgz#a79e4d3f82d5d72a82ee177aeaa791e793bbe5d6"
|
||||
dependencies:
|
||||
@ -7538,6 +7560,15 @@ recast@0.11.12, recast@^0.11.5:
|
||||
private "~0.1.5"
|
||||
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:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
||||
@ -8763,6 +8794,12 @@ supports-color@^3.1.0, supports-color@^3.1.2, supports-color@^3.2.3:
|
||||
dependencies:
|
||||
has-flag "^1.0.0"
|
||||
|
||||
supports-color@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.1.0.tgz#92cc14bb3dad8928ca5656c33e19a19f20af5c7a"
|
||||
dependencies:
|
||||
has-flag "^2.0.0"
|
||||
|
||||
svg-tags@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
|
||||
@ -9502,17 +9539,18 @@ vfile-location@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.1.tgz#0bf8816f732b0f8bd902a56fda4c62c8e935dc52"
|
||||
|
||||
vfile-reporter@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vfile-reporter/-/vfile-reporter-3.0.0.tgz#fe50714e373e0d2940510038a99bd609bdc8209f"
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/vfile-reporter/-/vfile-reporter-3.1.0.tgz#a9b398c5e6dcbc8a9a08e6cf425f092e86a37000"
|
||||
dependencies:
|
||||
chalk "^1.1.0"
|
||||
log-symbols "^1.0.2"
|
||||
plur "^2.0.0"
|
||||
repeat-string "^1.5.0"
|
||||
string-width "^1.0.0"
|
||||
strip-ansi "^3.0.1"
|
||||
trim "0.0.1"
|
||||
supports-color "^4.1.0"
|
||||
unist-util-stringify-position "^1.0.0"
|
||||
vfile-statistics "^1.0.0"
|
||||
|
||||
vfile-statistics@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vfile-statistics/-/vfile-statistics-1.0.0.tgz#003d356c0f3e0233f3a2271c65e2acee5ed4d0f8"
|
||||
|
||||
vfile@^2.0.0:
|
||||
version "2.1.0"
|
||||
|
Loading…
Reference in New Issue
Block a user