import jsYaml from "js-yaml"; import { compile } from "path-to-regexp"; import { autobind, formatDuration } from "../../utils"; import capitalize from "lodash/capitalize"; import { apiBase } from "../index"; import { helmChartStore } from "../../components/+apps-helm-charts/helm-chart.store"; import { ItemObject } from "../../item.store"; import { KubeObject } from "../kube-object"; interface IReleasePayload { name: string; namespace: string; version: string; config: string; // release values manifest: string; info: { deleted: string; description: string; first_deployed: string; last_deployed: string; notes: string; status: string; }; } interface IReleaseRawDetails extends IReleasePayload { resources: string; } export interface IReleaseDetails extends IReleasePayload { resources: KubeObject[]; } export interface IReleaseCreatePayload { name?: string; repo: string; chart: string; namespace: string; version: string; values: string; } export interface IReleaseUpdatePayload { repo: string; chart: string; version: string; values: string; } export interface IReleaseUpdateDetails { log: string; release: IReleaseDetails; } export interface IReleaseRevision { revision: number; updated: string; status: string; chart: string; description: string; } const endpoint = compile(`/v2/releases/:namespace?/:name?`) as ( params?: { namespace?: string; name?: string; } ) => string; export const helmReleasesApi = { list(namespace?: string) { return apiBase .get(endpoint({ namespace })) .then(releases => releases.map(HelmRelease.create)); }, get(name: string, namespace: string) { const path = endpoint({ name, namespace }); return apiBase.get(path).then(details => { const items: KubeObject[] = JSON.parse(details.resources).items; const resources = items.map(item => KubeObject.create(item)); return { ...details, resources }; }); }, create(payload: IReleaseCreatePayload): Promise { const { repo, ...data } = payload; data.chart = `${repo}/${data.chart}`; data.values = jsYaml.safeLoad(data.values); return apiBase.post(endpoint(), { data }); }, update(name: string, namespace: string, payload: IReleaseUpdatePayload): Promise { const { repo, ...data } = payload; data.chart = `${repo}/${data.chart}`; data.values = jsYaml.safeLoad(data.values); return apiBase.put(endpoint({ name, namespace }), { data }); }, async delete(name: string, namespace: string) { const path = endpoint({ name, namespace }); return apiBase.del(path); }, getValues(name: string, namespace: string) { const path = endpoint({ name, namespace }) + "/values"; return apiBase.get(path); }, getHistory(name: string, namespace: string): Promise { const path = endpoint({ name, namespace }) + "/history"; return apiBase.get(path); }, rollback(name: string, namespace: string, revision: number) { const path = endpoint({ name, namespace }) + "/rollback"; return apiBase.put(path, { data: { revision: revision } }); } }; @autobind() export class HelmRelease implements ItemObject { constructor(data: any) { Object.assign(this, data); } static create(data: any) { return new HelmRelease(data); } appVersion: string; name: string; namespace: string; chart: string; status: string; updated: string; revision: string; getId() { return this.namespace + this.name; } getName() { return this.name; } getNs() { return this.namespace; } getChart(withVersion = false) { let chart = this.chart; if(!withVersion && this.getVersion() != "" ) { const search = new RegExp(`-${this.getVersion()}`); chart = chart.replace(search, ""); } return chart; } getRevision() { return parseInt(this.revision, 10); } getStatus() { return capitalize(this.status); } getVersion() { const versions = this.chart.match(/(v?\d+)[^-].*$/); if (versions) { return versions[0]; } else { return ""; } } getUpdated(humanize = true, compact = true) { const now = new Date().getTime(); const updated = this.updated.replace(/\s\w*$/, ""); // 2019-11-26 10:58:09 +0300 MSK -> 2019-11-26 10:58:09 +0300 to pass into Date() const updatedDate = new Date(updated).getTime(); const diff = now - updatedDate; if (humanize) { return formatDuration(diff, compact); } return diff; } // Helm does not store from what repository the release is installed, // so we have to try to guess it by searching charts async getRepo() { const chartName = this.getChart(); const version = this.getVersion(); const versions = await helmChartStore.getVersions(chartName); const chartVersion = versions.find(chartVersion => chartVersion.version === version); return chartVersion ? chartVersion.repo : ""; } }