mirror of
https://github.com/yldio/copilot.git
synced 2024-12-01 07:30:07 +02:00
feat(cp-frontend): Move portal query to header, display result, return user from mock server
This commit is contained in:
parent
d2ac10ae28
commit
5ffa07aeee
@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Img } from 'normalized-styled-components';
|
import { Img } from 'normalized-styled-components';
|
||||||
@ -7,6 +8,7 @@ import unitcalc from 'unitcalc';
|
|||||||
|
|
||||||
import Logo from '@assets/triton_logo.png';
|
import Logo from '@assets/triton_logo.png';
|
||||||
import { Col, Row } from 'react-styled-flexboxgrid';
|
import { Col, Row } from 'react-styled-flexboxgrid';
|
||||||
|
import { P } from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
const StyledHeader = styled.div`
|
const StyledHeader = styled.div`
|
||||||
background-color: ${props => props.theme.primaryDarkBrand};
|
background-color: ${props => props.theme.primaryDarkBrand};
|
||||||
@ -18,14 +20,33 @@ const StyledLogo = styled(Img)`
|
|||||||
height: ${remcalc(25)};
|
height: ${remcalc(25)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default () => (
|
const StyledP = styled(P)`
|
||||||
|
color: ${props => props.theme.white};
|
||||||
|
font-weight: 600;
|
||||||
|
margin: ${unitcalc(0.5)} 0 0 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Header = ({ datacenter, username }) => (
|
||||||
<StyledHeader>
|
<StyledHeader>
|
||||||
<Row>
|
<Row>
|
||||||
<Col lg={12} xs={12}>
|
<Col xs={6} sm={8} md={10}>
|
||||||
<Link to="/">
|
<Link to="/">
|
||||||
<StyledLogo src={Logo} />
|
<StyledLogo src={Logo} />
|
||||||
</Link>
|
</Link>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col xs={3} sm={2} md={1}>
|
||||||
|
<StyledP>{datacenter}</StyledP>
|
||||||
|
</Col>
|
||||||
|
<Col xs={3} sm={2} md={1}>
|
||||||
|
<StyledP>{username}</StyledP>
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</StyledHeader>
|
</StyledHeader>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Header.propTypes = {
|
||||||
|
datacenter: PropTypes.string,
|
||||||
|
username: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Header;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
// import PropTypes from 'prop-types';
|
// Import PropTypes from 'prop-types';
|
||||||
import { compose, graphql } from 'react-apollo';
|
import { compose, graphql } from 'react-apollo';
|
||||||
import PortalQuery from '@graphql/Portal.gql';
|
|
||||||
import InstancesQuery from '@graphql/Instances.gql';
|
import InstancesQuery from '@graphql/Instances.gql';
|
||||||
|
|
||||||
import { LayoutContainer } from '@components/layout';
|
import { LayoutContainer } from '@components/layout';
|
||||||
@ -49,8 +48,6 @@ class InstanceList extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PortalGql = graphql(PortalQuery, {});
|
|
||||||
|
|
||||||
const InstanceListGql = graphql(InstancesQuery, {
|
const InstanceListGql = graphql(InstancesQuery, {
|
||||||
options(props) {
|
options(props) {
|
||||||
const params = props.match.params;
|
const params = props.match.params;
|
||||||
@ -75,6 +72,6 @@ const InstanceListGql = graphql(InstancesQuery, {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const InstanceListWithData = compose(PortalGql, InstanceListGql)(InstanceList);
|
const InstanceListWithData = compose(InstanceListGql)(InstanceList);
|
||||||
|
|
||||||
export default InstanceListWithData;
|
export default InstanceListWithData;
|
||||||
|
32
packages/cp-frontend/src/containers/navigation/header.js
Normal file
32
packages/cp-frontend/src/containers/navigation/header.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { graphql } from 'react-apollo';
|
||||||
|
import PortalQuery from '@graphql/Portal.gql';
|
||||||
|
import { Header as HeaderComponent } from '@components/navigation';
|
||||||
|
|
||||||
|
const Header = ({
|
||||||
|
portal = {
|
||||||
|
datacenter: {
|
||||||
|
region: ''
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
firstName: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loading,
|
||||||
|
error
|
||||||
|
}) => (
|
||||||
|
<HeaderComponent
|
||||||
|
datacenter={portal.datacenter.region}
|
||||||
|
username={portal.user.firstName}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const HeaderWithData = graphql(PortalQuery, {
|
||||||
|
props: ({ data: { portal, loading, error } }) => ({
|
||||||
|
portal,
|
||||||
|
loading,
|
||||||
|
error
|
||||||
|
})
|
||||||
|
})(Header);
|
||||||
|
|
||||||
|
export default HeaderWithData;
|
@ -1,2 +1,3 @@
|
|||||||
|
export { default as Header } from './header';
|
||||||
export { default as Breadcrumb } from './breadcrumb';
|
export { default as Breadcrumb } from './breadcrumb';
|
||||||
export { default as Menu } from './menu';
|
export { default as Menu } from './menu';
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { compose, graphql } from 'react-apollo';
|
import { compose, graphql } from 'react-apollo';
|
||||||
// import { connect } from 'react-redux';
|
// Import { connect } from 'react-redux';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
// import { Link } from 'react-router-dom';
|
// Import { Link } from 'react-router-dom';
|
||||||
import PortalQuery from '@graphql/Portal.gql';
|
|
||||||
import ServicesQuery from '@graphql/Services.gql';
|
import ServicesQuery from '@graphql/Services.gql';
|
||||||
|
|
||||||
import { processServices } from '@root/state/selectors';
|
import { processServices } from '@root/state/selectors';
|
||||||
@ -58,8 +57,6 @@ class ServiceList extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PortalGql = graphql(PortalQuery, {});
|
|
||||||
|
|
||||||
const ServicesGql = graphql(ServicesQuery, {
|
const ServicesGql = graphql(ServicesQuery, {
|
||||||
options(props) {
|
options(props) {
|
||||||
return {
|
return {
|
||||||
@ -78,6 +75,6 @@ const ServicesGql = graphql(ServicesQuery, {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const ServiceListWithData = compose(PortalGql, ServicesGql)(ServiceList);
|
const ServiceListWithData = compose(ServicesGql)(ServiceList);
|
||||||
|
|
||||||
export default ServiceListWithData;
|
export default ServiceListWithData;
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { compose, graphql } from 'react-apollo';
|
import { compose, graphql } from 'react-apollo';
|
||||||
// import { connect } from 'react-redux';
|
// Import { connect } from 'react-redux';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import PortalQuery from '@graphql/Portal.gql';
|
|
||||||
import ServicesQuery from '@graphql/ServicesTopology.gql';
|
import ServicesQuery from '@graphql/ServicesTopology.gql';
|
||||||
import unitcalc from 'unitcalc';
|
import unitcalc from 'unitcalc';
|
||||||
|
|
||||||
@ -10,12 +9,12 @@ import { processServices } from '@root/state/selectors';
|
|||||||
|
|
||||||
import { LayoutContainer } from '@components/layout';
|
import { LayoutContainer } from '@components/layout';
|
||||||
import { Loader, ErrorMessage } from '@components/messaging';
|
import { Loader, ErrorMessage } from '@components/messaging';
|
||||||
// import { ServicesTooltip } from '@components/services';
|
// Import { ServicesTooltip } from '@components/services';
|
||||||
|
|
||||||
/* import { Topology } from 'joyent-ui-toolkit'; */
|
import { Topology } from 'joyent-ui-toolkit';
|
||||||
/*import ServicesTooltip from '@components/services/tooltip';
|
/* Import ServicesTooltip from '@components/services/tooltip';
|
||||||
|
|
||||||
import { toggleTooltip } from '@state/actions';*/
|
import { toggleTooltip } from '@state/actions'; */
|
||||||
|
|
||||||
const StyledBackground = styled.div`
|
const StyledBackground = styled.div`
|
||||||
background-color: ${props => props.theme.whiteActive};
|
background-color: ${props => props.theme.whiteActive};
|
||||||
@ -44,14 +43,12 @@ const ServicesTopology = ({ push, services, datacenter, loading, error }) => {
|
|||||||
return (
|
return (
|
||||||
<StyledBackground>
|
<StyledBackground>
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
{/* <Topology services={services} /> */}
|
<Topology services={services} />
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
</StyledBackground>
|
</StyledBackground>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const PortalGql = graphql(PortalQuery, {});
|
|
||||||
|
|
||||||
const ServicesGql = graphql(ServicesQuery, {
|
const ServicesGql = graphql(ServicesQuery, {
|
||||||
options(props) {
|
options(props) {
|
||||||
return {
|
return {
|
||||||
@ -69,8 +66,6 @@ const ServicesGql = graphql(ServicesQuery, {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const ServicesTopologyWithData = compose(PortalGql, ServicesGql)(
|
const ServicesTopologyWithData = compose(ServicesGql)(ServicesTopology);
|
||||||
ServicesTopology
|
|
||||||
);
|
|
||||||
|
|
||||||
export default ServicesTopologyWithData;
|
export default ServicesTopologyWithData;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
query Portal {
|
query Portal {
|
||||||
portal {
|
portal {
|
||||||
username
|
user {
|
||||||
|
firstName
|
||||||
|
}
|
||||||
datacenter {
|
datacenter {
|
||||||
uuid
|
uuid
|
||||||
region
|
region
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
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 { Header } from '@components/navigation';
|
import { Header, Breadcrumb, Menu } from '@containers/navigation';
|
||||||
|
|
||||||
import { Breadcrumb, Menu } from '@containers/navigation';
|
|
||||||
|
|
||||||
import { DeploymentGroupList } from '@containers/deployment-groups';
|
import { DeploymentGroupList } from '@containers/deployment-groups';
|
||||||
import {
|
import {
|
||||||
|
@ -4,7 +4,13 @@
|
|||||||
"region": "us-east-1"
|
"region": "us-east-1"
|
||||||
},
|
},
|
||||||
"portal": {
|
"portal": {
|
||||||
"username": "juditgreskovits"
|
"user": {
|
||||||
|
"uuid": "uuid",
|
||||||
|
"login": "juditgreskovits",
|
||||||
|
"firstName": "Judit",
|
||||||
|
"lastName": "Greskovits",
|
||||||
|
"email": "name@email.com"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"deploymentGroups": [
|
"deploymentGroups": [
|
||||||
{
|
{
|
||||||
|
@ -1,77 +1,85 @@
|
|||||||
scalar Date
|
|
||||||
scalar Object
|
|
||||||
|
|
||||||
type Portal {
|
scalar Date
|
||||||
username: String!
|
scalar Object
|
||||||
datacenter: Datacenter! # we can infer dockerhost from this
|
|
||||||
|
type Portal {
|
||||||
|
user: User!
|
||||||
|
datacenter: Datacenter!
|
||||||
deploymentGroups: [DeploymentGroup]!
|
deploymentGroups: [DeploymentGroup]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeploymentGroup {
|
type User {
|
||||||
|
uuid: ID!
|
||||||
|
firstName: String!
|
||||||
|
lastName: String!
|
||||||
|
email: String!
|
||||||
|
login: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeploymentGroup {
|
||||||
uuid: ID!
|
uuid: ID!
|
||||||
name: String!
|
name: String!
|
||||||
slug: String!
|
slug: String!
|
||||||
services(slug: String): [Service]!
|
services(slug: String): [Service]!
|
||||||
version: Version!
|
version: Version!
|
||||||
history: [Version]!
|
history: [Version]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServiceScale {
|
type ServiceScale {
|
||||||
uuid: ID!
|
uuid: ID!
|
||||||
serviceName: String!
|
serviceName: String!
|
||||||
replicas: Int!
|
replicas: Int!
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ConvergenceActionType {
|
enum ConvergenceActionType {
|
||||||
NOOP
|
NOOP
|
||||||
CREATE
|
CREATE
|
||||||
RECREATE
|
RECREATE
|
||||||
START
|
START
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConvergenceAction {
|
type ConvergenceAction {
|
||||||
uuid: ID!
|
uuid: String!
|
||||||
type: ConvergenceActionType!
|
type: ConvergenceActionType!
|
||||||
service: String! # service name
|
service: String! # service name
|
||||||
machines: [String]! # instance machine ids
|
machines: [String]! # instance machine ids
|
||||||
}
|
}
|
||||||
|
|
||||||
type StateConvergencePlan {
|
type StateConvergencePlan {
|
||||||
uuid: ID!
|
uuid: String!
|
||||||
running: Boolean!
|
running: Boolean!
|
||||||
actions: [ConvergenceAction]!
|
actions: [ConvergenceAction]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Version {
|
type Version {
|
||||||
uuid: ID!
|
|
||||||
created: Date! # Either Int or define scalar
|
created: Date! # Either Int or define scalar
|
||||||
manifest: Manifest!
|
manifest: Manifest!
|
||||||
scale: [ServiceScale]!
|
scale: [ServiceScale]!
|
||||||
plan: StateConvergencePlan
|
plan: StateConvergencePlan
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ManifestType {
|
enum ManifestType {
|
||||||
COMPOSE
|
COMPOSE
|
||||||
MARIPOSA
|
MARIPOSA
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ManifestFormat {
|
enum ManifestFormat {
|
||||||
JSON
|
JSON
|
||||||
YAML
|
YAML
|
||||||
}
|
}
|
||||||
|
|
||||||
type Manifest {
|
type Manifest {
|
||||||
uuid: ID!
|
uuid: String!
|
||||||
created: Date!
|
created: Date!
|
||||||
type: ManifestType!
|
type: ManifestType!
|
||||||
format: ManifestFormat!
|
format: ManifestFormat!
|
||||||
raw: String!
|
raw: String!
|
||||||
obj: Object!
|
obj: Object!
|
||||||
}
|
}
|
||||||
|
|
||||||
# immutable
|
# immutable
|
||||||
type Service {
|
type Service {
|
||||||
uuid: ID! # unique id for db row
|
uuid: String! # unique id for db row
|
||||||
hash: String! # unique id for version of service
|
hash: String! # unique id for version of service
|
||||||
name: String! # human readable name
|
name: String! # human readable name
|
||||||
slug: String!
|
slug: String!
|
||||||
@ -81,10 +89,10 @@ type Service {
|
|||||||
connections: [String!] # list of serviceUuids
|
connections: [String!] # list of serviceUuids
|
||||||
parent: ID # parent service uuid
|
parent: ID # parent service uuid
|
||||||
package: Package! # we don't have this in current mock data
|
package: Package! # we don't have this in current mock data
|
||||||
}
|
}
|
||||||
|
|
||||||
# for metrics max / min (I guess)
|
# for metrics max / min (I guess)
|
||||||
type Package {
|
type Package {
|
||||||
uuid: ID!
|
uuid: ID!
|
||||||
name: String!
|
name: String!
|
||||||
type: String!
|
type: String!
|
||||||
@ -95,58 +103,75 @@ type Package {
|
|||||||
vcpus: Int!
|
vcpus: Int!
|
||||||
version: String!
|
version: String!
|
||||||
group: String!
|
group: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
enum InstanceStatus {
|
enum InstanceStatus {
|
||||||
CREATED
|
CREATED
|
||||||
RESTARTING
|
RESTARTING
|
||||||
RUNNING
|
RUNNING
|
||||||
PAUSED
|
PAUSED
|
||||||
EXITED
|
EXITED
|
||||||
DELETED
|
DELETED
|
||||||
}
|
}
|
||||||
|
|
||||||
type Instance {
|
type Instance {
|
||||||
uuid: ID!
|
uuid: String!
|
||||||
slug: String!
|
|
||||||
name: String!
|
name: String!
|
||||||
machineId: String!
|
machineId: String!
|
||||||
status: InstanceStatus!
|
status: InstanceStatus!
|
||||||
# metrics: [InstanceMetric]!
|
# metrics: [InstanceMetric]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Datacenter {
|
type Datacenter {
|
||||||
uuid: String!
|
uuid: String!
|
||||||
# name: String! # Do we have 'official' human readable names?
|
# name: String! # Do we have 'official' human readable names?
|
||||||
region: String!
|
region: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type InstanceMetric {
|
type InstanceMetric {
|
||||||
type: MetricType!
|
type: MetricType!
|
||||||
data: [MetricData]!
|
data: [MetricData]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type CurrentMetric {
|
type CurrentMetric {
|
||||||
name: String!
|
name: String!
|
||||||
value: Float!
|
value: Float!
|
||||||
measurement: String!
|
measurement: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type MetricType {
|
type MetricType {
|
||||||
uuid: ID!
|
uuid: String!
|
||||||
name: String!
|
name: String!
|
||||||
id: String!
|
id: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
type MetricData {
|
type MetricData {
|
||||||
timestamp: Int!
|
timestamp: Int!
|
||||||
value: Float!
|
value: Float!
|
||||||
}
|
}
|
||||||
|
|
||||||
# we probably wont use some of these queries or arguments
|
# Need to review queries
|
||||||
# but this way we expose the entire db through gql
|
type Query {
|
||||||
type Query {
|
|
||||||
portal: Portal
|
portal: Portal
|
||||||
|
deploymentGroups: [DeploymentGroup]
|
||||||
|
deploymentGroup(uuid: String, slug: String): DeploymentGroup
|
||||||
|
services(deploymentGroupUuid: String, deploymentGroupSlug: String): [Service]
|
||||||
|
service(uuid: String, slug: String): Service
|
||||||
|
instances(serviceUuid: String, serviceSlug: String): [Instance]
|
||||||
|
instance(uuid: String, machineId: String): Instance
|
||||||
|
metricTypes: [MetricType]
|
||||||
|
metricData(instanceUuid: String!, metricType: String!, from: Date!, to: Date!): [InstanceMetric]!
|
||||||
|
package: Package
|
||||||
|
datacenters: [Datacenter]
|
||||||
|
# tmp test
|
||||||
|
instanceMetric: InstanceMetric!
|
||||||
|
}
|
||||||
|
|
||||||
|
# we probably wont use some of these queries or arguments
|
||||||
|
# but this way we expose the entire db through gql
|
||||||
|
type Query {
|
||||||
|
portal: Portal
|
||||||
|
user: User
|
||||||
deploymentGroups(name: String, slug: String): [DeploymentGroup]
|
deploymentGroups(name: String, slug: String): [DeploymentGroup]
|
||||||
deploymentGroup(uuid: ID, name: String, slug: String): DeploymentGroup
|
deploymentGroup(uuid: ID, name: String, slug: String): DeploymentGroup
|
||||||
serviceScales(serviceName: String, versionUuid: ID): [ServiceScale]
|
serviceScales(serviceName: String, versionUuid: ID): [ServiceScale]
|
||||||
@ -166,18 +191,23 @@ type Query {
|
|||||||
instances(name: String!, machineId: ID, status: InstanceStatus, serviceUuid: ID, serviceSlug: String, deploymentGroupUuid: ID, deploymentGroupSlug: String): [Instance]
|
instances(name: String!, machineId: ID, status: InstanceStatus, serviceUuid: ID, serviceSlug: String, deploymentGroupUuid: ID, deploymentGroupSlug: String): [Instance]
|
||||||
instance(uuid: ID!): Instance
|
instance(uuid: ID!): Instance
|
||||||
datacenter(uuid: ID, region: String): Datacenter
|
datacenter(uuid: ID, region: String): Datacenter
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
createDeploymentGroup(name: String!) : DeploymentGroup
|
createDeploymentGroup(name: String!) : DeploymentGroup
|
||||||
updateDeploymentGroup(uuid: ID!, name: String!) : DeploymentGroup
|
updateDeploymentGroup(uuid: ID!, name: String!) : DeploymentGroup
|
||||||
|
|
||||||
provisionManifest(deploymentGroupUuid: ID!, type: ManifestType!, format: ManifestFormat!, raw: String!) : Version
|
provisionManifest(deploymentGroupUuid: ID!, type: ManifestType!, format: ManifestFormat!, raw: String!) : Version
|
||||||
scale(service: ID!, replicas: Int!) : Version
|
scale(service: ID!, replicas: Int!) : Version
|
||||||
|
|
||||||
stopServices(uuids: [ID]!) : [Service]
|
stopServices(uuids: [ID]!) : [Service]
|
||||||
startServices(uuids: [ID]!) : [Service]
|
startServices(uuids: [ID]!) : [Service]
|
||||||
restartServices(uuids: [ID]!) : [Service]
|
restartServices(uuids: [ID]!) : [Service]
|
||||||
deleteServices(uuids: [ID]!) : [Service]
|
deleteServices(uuids: [ID]!) : [Service]
|
||||||
|
|
||||||
stopInstances(uuids: [ID]!) : [Instance]
|
stopInstances(uuids: [ID]!) : [Instance]
|
||||||
startInstances(uuids: [ID]!) : [Instance]
|
startInstances(uuids: [ID]!) : [Instance]
|
||||||
restartInstances(uuids: [ID]!) : [Instance]
|
restartInstances(uuids: [ID]!) : [Instance]
|
||||||
}
|
|
||||||
|
# reprovision() ???
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user