import "./add-secret-dialog.scss"; import React from "react"; import { observable } from "mobx"; import { observer } from "mobx-react"; import { t, Trans } from "@lingui/macro"; import { _i18n } from "../../i18n"; import { Dialog, DialogProps } from "../dialog"; import { Wizard, WizardStep } from "../wizard"; import { Input } from "../input"; import { systemName } from "../input/input.validators"; import { Secret, secretsApi, SecretType } from "../../api/endpoints"; import { SubTitle } from "../layout/sub-title"; import { NamespaceSelect } from "../+namespaces/namespace-select"; import { Select, SelectOption } from "../select"; import { Icon } from "../icon"; import { KubeObjectMetadata } from "../../api/kube-object"; import { base64 } from "../../utils"; import { Notifications } from "../notifications"; import { showDetails } from "../../navigation"; import upperFirst from "lodash/upperFirst"; interface Props extends Partial { } interface SecretTemplateField { key: string; value?: string; required?: boolean; } interface SecretTemplate { [field: string]: SecretTemplateField[]; annotations?: SecretTemplateField[]; labels?: SecretTemplateField[]; data?: SecretTemplateField[]; } type SecretField = keyof SecretTemplate; type RecursivePartial = { [P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial[] : T[P] extends object ? RecursivePartial : T[P]; }; @observer export class AddSecretDialog extends React.Component { @observable static isOpen = false; static open(): void { AddSecretDialog.isOpen = true; } static close(): void { AddSecretDialog.isOpen = false; } private secretTemplate: Partial> = { [SecretType.Opaque]: {}, [SecretType.ServiceAccountToken]: { annotations: [ { key: "kubernetes.io/service-account.name", required: true }, { key: "kubernetes.io/service-account.uid", required: true } ], }, } get types(): SecretType[] { return Object.keys(this.secretTemplate) as SecretType[]; } @observable secret = this.secretTemplate; @observable name = ""; @observable namespace = "default"; @observable type = SecretType.Opaque; reset = (): void => { this.name = ""; this.secret = this.secretTemplate; } close = (): void => { AddSecretDialog.close(); } private getDataFromFields = (fields: SecretTemplateField[] = [], processValue?: (val: string) => string): any => { return fields.reduce((data, field) => { const { key, value } = field; if (key) { data[key] = processValue ? processValue(value) : value; } return data; }, {}); } createSecret = async (): Promise => { const { name, namespace, type } = this; const { data = [], labels = [], annotations = [] } = this.secret[type]; const metadata: Partial = { name, namespace, annotations: this.getDataFromFields(annotations), labels: this.getDataFromFields(labels), }; const secret: Partial = { type: type, data: this.getDataFromFields(data, val => val ? base64.encode(val) : ""), metadata: metadata as KubeObjectMetadata, }; try { const newSecret = await secretsApi.create({ namespace, name }, secret); showDetails(newSecret.selfLink); this.reset(); this.close(); } catch (err) { Notifications.error(err); } } addField = (field: SecretField): void => { const fields = this.secret[this.type][field] || []; fields.push({ key: "", value: "" }); this.secret[this.type][field] = fields; } removeField = (field: SecretField, index: number): void => { const fields = this.secret[this.type][field] || []; fields.splice(index, 1); } renderFields(field: SecretField): JSX.Element { const fields = this.secret[this.type][field] || []; return ( <> this.addField(field)} />
{fields.map((item, index) => { const { key = "", value = "", required } = item; return (
{ item.key = v; }} /> { item.value = v; }} /> Required field : Remove field} className="remove-icon" material="remove_circle_outline" onClick={(): void => this.removeField(field, index)} />
); })}
); } render(): JSX.Element { const { ...dialogProps } = this.props; const { namespace, name, type } = this; const header =
Create Secret
; return ( Create} next={this.createSecret}>
Secret name}/> { this.name = v; }} />
Namespace}/> this.namespace = value} />
Secret type}/>