Skip to content

Commit

Permalink
Add UI for deploying values.yaml for charts (#41)
Browse files Browse the repository at this point in the history
* add values for installing charts

* rebase

* selectable version for values

* yaml mode

* modifying values

* combine readme and values into selectChartVersionAndGetFiles

* add yaml label to values
  • Loading branch information
sozercan authored and prydonius committed Feb 5, 2018
1 parent fc09740 commit 450a042
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 19 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"enzyme-adapter-react-16": "^1.1.1",
"raf": "^3.4.0",
"react": "^16.2.0",
"react-ace": "^5.9.0",
"react-dom": "^16.2.0",
"react-markdown": "^3.1.4",
"react-modal": "^3.1.11",
Expand Down
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<script src="//d1d5nb8vlsbujg.cloudfront.net/bitnami-ui/3.0.0-alpha-12/bitnami.ui.min.js"></script>
<title>React App</title>
<title>Kubeapps Dashboard</title>
</head>

<body>
Expand Down
4 changes: 2 additions & 2 deletions public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"short_name": "Kubeapps Dashboard",
"name": "Kubeapps Dashboard",
"icons": [
{
"src": "favicon.ico",
Expand Down
25 changes: 23 additions & 2 deletions src/actions/charts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,18 @@ export const selectReadme = createAction("SELECT_README", (readme: string) => ({
readme,
type: "SELECT_README",
}));
export const selectValues = createAction("SELECT_VALUES", (values: string) => ({
type: "SELECT_VALUES",
values,
}));

const allActions = [
requestCharts,
receiveCharts,
receiveChartVersions,
selectChartVersion,
selectReadme,
selectValues,
].map(getReturnOfExpression);
export type ChartsAction = typeof allActions[number];

Expand Down Expand Up @@ -68,15 +73,17 @@ export function fetchChartVersionsAndSelectVersion(id: string, version?: string)
cv = found;
}
dispatch(getChartReadme(id, cv.attributes.version));
dispatch(getChartValues(id, cv.attributes.version));
return dispatch(selectChartVersion(cv));
});
};
}

export function selectChartVersionAndGetReadme(cv: IChartVersion) {
export function selectChartVersionAndGetFiles(cv: IChartVersion) {
return (dispatch: Dispatch<IStoreState>): Promise<{}> => {
const id = `${cv.relationships.chart.data.repo.name}/${cv.relationships.chart.data.name}`;
dispatch(selectChartVersion(cv));
dispatch(getChartValues(id, cv.attributes.version));
return dispatch(getChartReadme(id, cv.attributes.version));
};
}
Expand All @@ -89,7 +96,20 @@ export function getChartReadme(id: string, version: string) {
};
}

export function deployChart(chartVersion: IChartVersion, releaseName: string, namespace: string) {
export function getChartValues(id: string, version: string) {
return (dispatch: Dispatch<IStoreState>): Promise<{}> => {
return fetch(url.api.charts.getValues(id, version))
.then(response => response.text())
.then(text => dispatch(selectValues(text)));
};
}

export function deployChart(
chartVersion: IChartVersion,
releaseName: string,
namespace: string,
values: string,
) {
return (dispatch: Dispatch<IStoreState>): Promise<{}> => {
const chartAttrs = chartVersion.relationships.chart.data;
return fetch(url.api.helmreleases.create(namespace), {
Expand All @@ -105,6 +125,7 @@ export function deployChart(chartVersion: IChartVersion, releaseName: string, na
spec: {
chartName: chartAttrs.name,
repoUrl: chartAttrs.repo.url,
values,
version: chartVersion.attributes.version,
},
}),
Expand Down
43 changes: 40 additions & 3 deletions src/components/ChartView/ChartDeployButton.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import * as React from "react";
import AceEditor from "react-ace";
import * as Modal from "react-modal";
import { RouterAction } from "react-router-redux";
import { IChartVersion } from "../../shared/types";

import "brace/mode/yaml";
import "brace/theme/xcode";

interface IChartDeployButtonProps {
version: IChartVersion;
deployChart: (chartVersion: IChartVersion, releaseName: string, namespace: string) => Promise<{}>;
deployChart: (
chartVersion: IChartVersion,
releaseName: string,
namespace: string,
values: string,
) => Promise<{}>;
push: (location: string) => RouterAction;
values: string;
}

interface IChartDeployButtonState {
Expand All @@ -15,6 +25,8 @@ interface IChartDeployButtonState {
// deployment options
releaseName: string;
namespace: string;
values: string;
valuesModified: boolean;
error: string | null;
}

Expand All @@ -25,8 +37,18 @@ class ChartDeployButton extends React.Component<IChartDeployButtonProps, IChartD
modalIsOpen: false,
namespace: "default",
releaseName: "",
values: "",
valuesModified: false,
};

public componentWillReceiveProps(nextProps: IChartDeployButtonProps) {
if (!this.state.valuesModified) {
this.setState({
values: nextProps.values,
});
}
}

public render() {
return (
<div className="ChartDeployButton">
Expand Down Expand Up @@ -64,6 +86,18 @@ class ChartDeployButton extends React.Component<IChartDeployButtonProps, IChartD
value={this.state.namespace}
/>
</div>
<div style={{ marginBottom: "1em" }}>
<label htmlFor="values">Values (YAML)</label>
<AceEditor
mode="yaml"
theme="xcode"
name="values"
width="100%"
onChange={this.handleValuesChange}
setOptions={{ showPrintMargin: false }}
value={this.state.values}
/>
</div>
<div>
<button className="button button-primary" type="submit">
Submit
Expand Down Expand Up @@ -94,8 +128,8 @@ class ChartDeployButton extends React.Component<IChartDeployButtonProps, IChartD
e.preventDefault();
const { version, deployChart, push } = this.props;
this.setState({ isDeploying: true });
const { releaseName, namespace } = this.state;
deployChart(version, releaseName, namespace)
const { releaseName, namespace, values } = this.state;
deployChart(version, releaseName, namespace, values)
.then(() => push(`/apps/${releaseName}`))
.catch(err => this.setState({ isDeploying: false, error: err.toString() }));
};
Expand All @@ -106,6 +140,9 @@ class ChartDeployButton extends React.Component<IChartDeployButtonProps, IChartD
public handleNamespaceChange = (e: React.FormEvent<HTMLInputElement>) => {
this.setState({ namespace: e.currentTarget.value });
};
public handleValuesChange = (value: string) => {
this.setState({ values: value, valuesModified: true });
};
}

export default ChartDeployButton;
22 changes: 16 additions & 6 deletions src/components/ChartView/ChartView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ import "./ChartView.css";
interface IChartViewProps {
chartID: string;
fetchChartVersionsAndSelectVersion: (id: string, version?: string) => Promise<{}>;
deployChart: (version: IChartVersion, releaseName: string, namespace: string) => Promise<{}>;
deployChart: (
version: IChartVersion,
releaseName: string,
namespace: string,
values: string,
) => Promise<{}>;
push: (location: string) => RouterAction;
isFetching: boolean;
selected: IChartState["selected"];
selectChartVersionAndGetReadme: (version: IChartVersion) => Promise<{}>;
selectChartVersionAndGetFiles: (version: IChartVersion) => Promise<{}>;
version: string | undefined;
}

Expand All @@ -27,12 +32,12 @@ class ChartView extends React.Component<IChartViewProps> {
}

public componentWillReceiveProps(nextProps: IChartViewProps) {
const { selectChartVersionAndGetReadme, version } = this.props;
const { selectChartVersionAndGetFiles, version } = this.props;
const { versions } = this.props.selected;
if (nextProps.version !== version) {
const cv = versions.find(v => v.attributes.version === nextProps.version);
if (cv) {
selectChartVersionAndGetReadme(cv);
selectChartVersionAndGetFiles(cv);
} else {
throw new Error("could not find chart");
}
Expand All @@ -41,7 +46,7 @@ class ChartView extends React.Component<IChartViewProps> {

public render() {
const { isFetching, deployChart, push } = this.props;
const { version, readme, versions } = this.props.selected;
const { version, readme, versions, values } = this.props.selected;
if (isFetching || !version) {
return <div>Loading</div>;
}
Expand All @@ -65,7 +70,12 @@ class ChartView extends React.Component<IChartViewProps> {
<aside className="ChartViewSidebar bg-light margin-v-big padding-h-normal padding-b-normal">
<div className="ChartViewSidebar__section">
<h2>Usage</h2>
<ChartDeployButton push={push} version={version} deployChart={deployChart} />
<ChartDeployButton
push={push}
version={version}
deployChart={deployChart}
values={values || ""}
/>
</div>
<div className="ChartViewSidebar__section">
<h2>Chart Versions</h2>
Expand Down
8 changes: 4 additions & 4 deletions src/containers/ChartViewContainer/ChartViewContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ function mapStateToProps({ charts }: IStoreState, { match: { params } }: IRouteP

function mapDispatchToProps(dispatch: Dispatch<IStoreState>) {
return {
deployChart: (version: IChartVersion, releaseName: string, namespace: string) =>
dispatch(actions.charts.deployChart(version, releaseName, namespace)),
deployChart: (version: IChartVersion, releaseName: string, namespace: string, values: string) =>
dispatch(actions.charts.deployChart(version, releaseName, namespace, values)),
fetchChartVersionsAndSelectVersion: (id: string, version?: string) =>
dispatch(actions.charts.fetchChartVersionsAndSelectVersion(id, version)),
push: (location: string) => dispatch(push(location)),
selectChartVersionAndGetReadme: (version: IChartVersion) =>
dispatch(actions.charts.selectChartVersionAndGetReadme(version)),
selectChartVersionAndGetFiles: (version: IChartVersion) =>
dispatch(actions.charts.selectChartVersionAndGetFiles(version)),
};
}

Expand Down
4 changes: 4 additions & 0 deletions src/reducers/charts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const chartsSelectedReducer = (
};
case getType(actions.charts.selectReadme):
return { ...state, readme: action.readme };
case getType(actions.charts.selectValues):
return { ...state, values: action.values };
default:
}
return state;
Expand All @@ -51,6 +53,8 @@ const chartsReducer = (state: IChartState = initialState, action: ChartsAction):
};
case getType(actions.charts.selectReadme):
return { ...state, selected: chartsSelectedReducer(state.selected, action) };
case getType(actions.charts.selectValues):
return { ...state, selected: chartsSelectedReducer(state.selected, action) };
default:
}
return state;
Expand Down
1 change: 1 addition & 0 deletions src/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export interface IChartState {
version?: IChartVersion;
versions: IChartVersion[];
readme?: string;
values?: string;
};
items: IChart[];
}
Expand Down
2 changes: 2 additions & 0 deletions src/shared/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export const api = {
get: (id: string) => `${api.charts.base}/charts/${id}`,
getReadme: (id: string, version: string) =>
`${api.charts.base}/assets/${id}/versions/${version}/README.md`,
getValues: (id: string, version: string) =>
`${api.charts.base}/assets/${id}/versions/${version}/values.yaml`,
list: (repo?: string) => `${api.charts.base}/charts${repo ? `/${repo}` : ""}`,
listVersions: (id: string) => `${api.charts.get(id)}/versions`,
},
Expand Down
23 changes: 22 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,10 @@ brace-expansion@^1.0.0, brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"

brace@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/brace/-/brace-0.11.0.tgz#155cd80607687dc8cb908f0df94e62a033c1d563"

braces@^1.8.2:
version "1.8.5"
resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
Expand Down Expand Up @@ -3942,6 +3946,14 @@ lodash.flattendeep@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"

lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"

lodash.isequal@^4.1.1:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"

lodash.isfunction@^3.0.8:
version "3.0.8"
resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.8.tgz#4db709fc81bc4a8fd7127a458a5346c5cdce2c6b"
Expand Down Expand Up @@ -5148,7 +5160,7 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"

prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.6.0:
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.0:
version "15.6.0"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856"
dependencies:
Expand Down Expand Up @@ -5291,6 +5303,15 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"

react-ace@^5.9.0:
version "5.9.0"
resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-5.9.0.tgz#427a1cc4869b960a6f9748aa7eb169a9269fc336"
dependencies:
brace "^0.11.0"
lodash.get "^4.4.2"
lodash.isequal "^4.1.1"
prop-types "^15.5.8"

react-dev-utils@4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-4.2.1.tgz#9f2763e7bafa1a1b9c52254d2a479deec280f111"
Expand Down

0 comments on commit 450a042

Please sign in to comment.