diff --git a/.gitignore b/.gitignore index c9de38e..5df51aa 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ .env.test.local .env.production.local .vscode +.idea npm-debug.log* yarn-debug.log* diff --git a/src/actions/catalog.ts b/src/actions/catalog.ts index 3e09c2e..a050ca0 100644 --- a/src/actions/catalog.ts +++ b/src/actions/catalog.ts @@ -1,14 +1,10 @@ import { Dispatch } from "redux"; import { createAction, getReturnOfExpression } from "typesafe-actions"; -import { - IServiceBinding, - IServiceBroker, - IServiceClass, - IServiceInstance, - IServicePlan, - ServiceCatalog, -} from "../shared/ServiceCatalog"; +import { IClusterServiceClass } from "../shared/ClusterServiceClass"; +import { IServiceBinding, ServiceBinding } from "../shared/ServiceBinding"; +import { IServiceBroker, IServicePlan, ServiceCatalog } from "../shared/ServiceCatalog"; +import { IServiceInstance, ServiceInstance } from "../shared/ServiceInstance"; import { IStoreState } from "../shared/types"; export const checkCatalogInstall = createAction("CHECK_INSTALL"); @@ -35,10 +31,13 @@ export const receiveBindings = createAction("RECEIVE_BINDINGS", (bindings: IServ type: "RECEIVE_BINDINGS", })); export const requestClasses = createAction("REQUEST_PLANS"); -export const receiveClasses = createAction("RECEIVE_CLASSES", (classes: IServiceClass[]) => ({ - classes, - type: "RECEIVE_CLASSES", -})); +export const receiveClasses = createAction( + "RECEIVE_CLASSES", + (classes: IClusterServiceClass[]) => ({ + classes, + type: "RECEIVE_CLASSES", + }), +); const actions = [ checkCatalogInstall, @@ -64,13 +63,7 @@ export function provision( parameters: {}, ) { return async (dispatch: Dispatch) => { - return ServiceCatalog.provisionInstance( - releaseName, - namespace, - className, - planName, - parameters, - ); + return ServiceInstance.create(releaseName, namespace, className, planName, parameters); }; } @@ -91,7 +84,7 @@ export type ServiceCatalogAction = typeof actions[number]; export function getBindings() { return async (dispatch: Dispatch) => { dispatch(requestBindings()); - const bindings = await ServiceCatalog.getServiceBindings(); + const bindings = await ServiceBinding.list(); dispatch(receiveBindings(bindings)); return bindings; }; @@ -118,7 +111,7 @@ export function getClasses() { export function getInstances() { return async (dispatch: Dispatch) => { dispatch(requestInstances()); - const instances = await ServiceCatalog.getServiceInstances(); + const instances = await ServiceInstance.list(); dispatch(receiveInstances(instances)); return instances; }; diff --git a/src/components/AppRepoList/AppRepoButton.tsx b/src/components/AppRepoList/AppRepoButton.tsx index 99c1ead..da24798 100644 --- a/src/components/AppRepoList/AppRepoButton.tsx +++ b/src/components/AppRepoList/AppRepoButton.tsx @@ -28,11 +28,12 @@ export const AppRepoForm = (props: IAppRepoFormProps) => {

Add an App Repository

+
+ + {this.state.error && ( +
{this.state.error}
+ )} +
+

Add Binding

+ +
+ +
+ + +
+
+
+ ); + } + + private closeModal = () => this.setState({ modalIsOpen: false }); + private openModal = () => this.setState({ modalIsOpen: true }); + private handleNameChange = (e: React.ChangeEvent) => + this.setState({ bindingName: e.target.value }); + private handleInstanceNameChange = (e: React.ChangeEvent) => + this.setState({ instanceRefName: e.target.value }); + private handleNamespaceChange = (e: React.ChangeEvent) => + this.setState({ namespace: e.target.value }); + private bind = async () => { + await this.props.addBinding( + this.state.bindingName, + this.state.instanceRefName, + this.state.namespace, + ); + this.closeModal(); + }; +} diff --git a/src/components/BrokerView/RemoveBindingButton.tsx b/src/components/BrokerView/RemoveBindingButton.tsx new file mode 100644 index 0000000..19f523e --- /dev/null +++ b/src/components/BrokerView/RemoveBindingButton.tsx @@ -0,0 +1,28 @@ +import * as React from "react"; +import { IServiceBinding, ServiceBinding } from "../../shared/ServiceBinding"; + +interface IRemoveBindingButtonProps { + binding: IServiceBinding; + onRemoveComplete?: () => Promise; +} + +export class RemoveBindingButton extends React.Component { + public render() { + return ( +
+ +
+ ); + } + + private handleRemoveBindingClick = async () => { + const { binding, onRemoveComplete } = this.props; + const { name, namespace } = binding.metadata; + await ServiceBinding.delete(name, namespace); + if (onRemoveComplete) { + await onRemoveComplete(); + } + }; +} diff --git a/src/components/BrokerView/index.tsx b/src/components/BrokerView/index.tsx index 101371b..bbecaf1 100644 --- a/src/components/BrokerView/index.tsx +++ b/src/components/BrokerView/index.tsx @@ -1,21 +1,20 @@ import * as React from "react"; import { Link } from "react-router-dom"; -import { - IServiceBinding, - IServiceBroker, - IServiceClass, - IServiceInstance, - IServicePlan, -} from "../../shared/ServiceCatalog"; +import { IClusterServiceClass } from "../../shared/ClusterServiceClass"; +import { IServiceBinding, ServiceBinding } from "../../shared/ServiceBinding"; +import { IServiceBroker, IServicePlan } from "../../shared/ServiceCatalog"; +import { IServiceInstance } from "../../shared/ServiceInstance"; import { Card, CardContainer } from "../Card"; import DeprovisionButton from "../DeprovisionButton"; import SyncButton from "../SyncButton"; +import { AddBindingButton } from "./AddBindingButton"; +import { RemoveBindingButton } from "./RemoveBindingButton"; export interface IBrokerViewProps { bindings: IServiceBinding[]; broker: IServiceBroker | undefined; - classes: IServiceClass[]; + classes: IClusterServiceClass[]; getCatalog: () => Promise; instances: IServiceInstance[]; plans: IServicePlan[]; @@ -56,6 +55,7 @@ export class BrokerView extends React.PureComponent { Instance Status Message + @@ -79,7 +79,15 @@ export class BrokerView extends React.PureComponent { {message} - +
+ + +
); @@ -109,8 +117,21 @@ export class BrokerView extends React.PureComponent { ["Port", secretPort], ["Username", secretUsername], ]; + const condition = [...binding.status.conditions].shift(); + const currentStatus = condition ? ( +
+
+ {condition.type}: {condition.status} +
+ {condition.message} +
+ ) : ( + undefined + ); + const body = (
+ {currentStatus} {statuses.map(statusPair => { const [key, value] = statusPair; return ( @@ -134,7 +155,12 @@ export class BrokerView extends React.PureComponent { key={binding.metadata.name} header={binding.metadata.name} body={body} - button={} + button={ + + } /> ); return card; @@ -145,4 +171,10 @@ export class BrokerView extends React.PureComponent {
); } + + private addbinding = async (bindingName: string, instanceName: string, namespace: string) => { + const binding = await ServiceBinding.create(bindingName, instanceName, namespace); + await this.props.getCatalog(); + return binding; + }; } diff --git a/src/components/ClassList/index.tsx b/src/components/ClassList/index.tsx index eeb2598..498108c 100644 --- a/src/components/ClassList/index.tsx +++ b/src/components/ClassList/index.tsx @@ -1,13 +1,14 @@ import * as React from "react"; -import { IServiceBroker, IServiceClass } from "../../shared/ServiceCatalog"; +import { IClusterServiceClass } from "../../shared/ClusterServiceClass"; +import { IServiceBroker } from "../../shared/ServiceCatalog"; import { Card, CardContainer } from "../Card"; export interface IClassListProps { broker: IServiceBroker | undefined; - classes: IServiceClass[]; + classes: IClusterServiceClass[]; getBrokers: () => Promise; - getClasses: () => Promise; + getClasses: () => Promise; } export class ClassList extends React.Component { diff --git a/src/components/ClassView/index.tsx b/src/components/ClassView/index.tsx index 6f54c2d..95feae5 100644 --- a/src/components/ClassView/index.tsx +++ b/src/components/ClassView/index.tsx @@ -1,12 +1,13 @@ import * as React from "react"; import { RouterAction } from "react-router-redux"; -import { IServiceClass, IServicePlan } from "../../shared/ServiceCatalog"; +import { IClusterServiceClass } from "../../shared/ClusterServiceClass"; +import { IServicePlan } from "../../shared/ServiceCatalog"; import { Card, CardContainer } from "../Card"; import ProvisionButton from "../ProvisionButton"; interface IClassViewProps { - classes: IServiceClass[]; + classes: IClusterServiceClass[]; classname: string; getCatalog: () => Promise; plans: IServicePlan[]; @@ -18,7 +19,7 @@ interface IClassViewProps { parameters: {}, ) => Promise; push: (location: string) => RouterAction; - svcClass: IServiceClass | undefined; + svcClass: IClusterServiceClass | undefined; } export class ClassView extends React.Component { diff --git a/src/components/DeprovisionButton/index.tsx b/src/components/DeprovisionButton/index.tsx index 7a20d8d..4abbbbd 100644 --- a/src/components/DeprovisionButton/index.tsx +++ b/src/components/DeprovisionButton/index.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { IServiceInstance } from "../../shared/ServiceCatalog"; +import { IServiceInstance } from "../../shared/ServiceInstance"; interface IDeprovisionButtonProps { instance: IServiceInstance; @@ -36,7 +36,7 @@ class DeprovisionButton extends React.Component {this.state.isDeprovisioning &&
Deprovisioning...
}